• 学习更新2021年10月


    2021-10-19

    一本通 1264:【例9.8】合唱队形

    一本通 1264:【例9.8】合唱队形

    一本通的题,想明白了很简单,想不明白比较复杂。就是从左到右是升序子序列,而从右边到左也是升序子序列。两个dp数组,一个从左到右计算最大升序子序列。一个从右往左计算最大升序子序列。最后做一个合并。看每个位置dp1[i]+dp2[i] 的最大值,减去重复的i位置的值,就是最大值了。

    public int res(int[] t) {
    
            int dp1[] = new int[t.length];
            int dp2[] = new int[t.length];
            for (int i = 0; i < t.length; i++) {
                dp1[i] = 1;
                for (int j = 0; j < 1; j++) {
                    if (t[i] > t[j]) {
                        dp1[i] = Math.max(dp1[j] + 1, dp1[i]);
                    }
                }
            }
    
            for (int i = t.length - 1; i >= 0; i--) {
                dp2[i] = 1;
                for (int j = t.length - 1; j > i; j--) {
                    if (t[i] > t[j]) {
                        dp2[i] = Math.max(dp2[j] + 1, dp2[i]);
                    }
                }
            }
    
            int max = 1;
            for (int i = 0; i < t.length; i++) {
                max = Math.max(dp1[i] + dp2[i], max);
            }
            System.out.println(max-1);
            return max - 1;
        }
    

    2021-10-20

    516. 最长回文子序列

    516. 最长回文子序列

    这题是非常经典的动态规划题,详细解析,后面补充。

    回文串、序列 的题,通常你要先定义两个指针,一个是指向起始位置,一个指向结束位置。所以都是二位dp数组

    • 1.dp[i][j]代表从索引 i到j位置的最长回文序列长度。则我们最终要求得最长回文序列为 dp[0][len-1]
    • 2.回文特点是对称。则dp[i][j]和dp[i+1][j-1]产生递推关系
    • 3.当i位置字符和j位置字符相同则 dp[i][j]=dp[i+1][j-1]+2,因为长度是在原来基础上增加2的
    • 3.当i位置字符和j位置字符不同则 dp[i][j]这个的最大值与下面两个位置产生的最长回文相同,因为i和j无效,位置一:i+1到j,位置二:i~j-1位置
    • 4.i如果从0开始遍历,则j在遍历过程中,比如i=0,j=3,则此时状态转移为 i=2,而此时i=2的dp我们还没计算出来,所以无法算得,所以i需要从len-1开始
    class Solution {
       public int longestPalindromeSubseq(String s) {
            if (s == null) {
                return 0;
            }
            int len = s.length();
            char[] cs = s.toCharArray();
            //状态转义方程式  当cs[i]==cs[j]
            // 则有dp[i][j]= dp[i+1][j-1]。
            // 否则dp[i][j] = Max(dp[i+1][j],dp[i][j-1])
            int[][] dp = new int[len][len];
    
            for (int i = len - 1; i >= 0; i--) {
                dp[i][i]=1;
                for (int j = i + 1; j < len; j++) {
                    if (cs[i] == cs[j]) {
                        dp[i][j] = dp[i + 1][j - 1]+2;
                    } else {
                        dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]);
                    }
                }
            }
            return dp[0][len - 1];
        }
    }
    

    2021-10-26

    首先说这两天的纪念意义,2020年10月27日是我在力扣上提交通过的第一道题,知道今天我通过了刚好350题

    P496. 下一个更大元素 I

    P496. 下一个更大元素 I
    这题暴力解法时间复杂度O(n2),这里使用单调栈和map来降低时间复杂度

    • 1.求得nums2每个位置上比当前位置大的元素的索引,并放入map
      • 1.1 倒序遍历(必须倒序),把元素索引放入栈,使得栈索引对应值保持单调递减的,也就是当前的元素的下一个元素一定在栈顶。如果不满足单调,就一直弹栈,直到拿到比当前更大的元素
    • 2.遍历nums1,找到其在map中对应的索引,去nums2取出来
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
            //i - index  ,i表示元素,index表示下一个比i大的数
            //[1,3,4,2,5]
            //用一个栈找到下一个比自己大的元素
            //栈里面保持逐渐增大的
    
            Map<Integer, Integer> map = new HashMap<>();
            Stack<Integer> stack = new Stack<>();
            for (int i = nums2.length - 1; i >= 0; i--) {
                if (stack.isEmpty() || nums2[i] < nums2[stack.peek()]) {
                    map.put(nums2[i], stack.isEmpty() ? -1 : stack.peek());
                    stack.add(i);
                } else {
                    while (!stack.isEmpty() && nums2[i] > nums2[stack.peek()]) {
                        stack.pop();
                    }
                    map.put(nums2[i], stack.isEmpty() ? -1 : stack.peek());
                    stack.add(i);
                }
            }
    
            int res[] = new int[nums1.length];
            for (int i = 0; i < nums1.length; i++) {
                res[i] = map.get(nums1[i]) == -1 ? -1 : nums2[map.get(nums1[i])];
            }
            return res;
        }
    

    P503. 下一个更大元素 II

    P503. 下一个更大元素 II
    这题要注意一些细节,使用的元素的索引去映射,因为元素可能重复,这样map会被覆盖。这题在原来基础上,首先要构造一个nums2数组,循环数组直接拼接两个数组能达到循环数组的效果

    class Solution {
        public int[] nextGreaterElements(int[] nums) {
    
            int nums2[] = new int[nums.length * 2];
            System.arraycopy(nums, 0, nums2, 0, nums.length);
            System.arraycopy(nums, 0, nums2, nums.length, nums.length);
            Map<Integer, Integer> map = new HashMap<>();
            Stack<Integer> stack = new Stack<>();
            for (int i = nums2.length - 1; i >= 0; i--) {
                 if (stack.isEmpty() || nums2[i] < nums2[stack.peek()]) {
    
                    map.put(i, stack.isEmpty() ? -1 : stack.peek());
                    stack.add(i);
                } else {
                    while (!stack.isEmpty() && nums2[i] >= nums2[stack.peek()]) {
                        stack.pop();
                    }
                    map.put(i, stack.isEmpty() ? -1 : stack.peek());
                    stack.add(i);
                }
            }
    
            int res[] = new int[nums.length];
            for (int i = 0; i < nums.length; i++) {
                res[i] = map.get(i) == -1 ? -1 : nums2[map.get(i)];
            }
            return res;
    
        }
    }
    
  • 相关阅读:
    个人软件过程 1
    一个月学会VC++2012 3.我们动手吧!
    一个月掌握VC++2010?
    个人软件过程2 项目开发的基本流程
    个人软件过程4 功能说明和用户体验设计
    一个月学会VC++2010 5.对话框的数据交换
    个人软件过程3 需求分析
    一个月学会VC++2010 4.细说对象之香艳旖旎
    一个月学会VC++2010 1.送上门的银子
    一个月学会VC++2010 2.看起来风险不大
  • 原文地址:https://www.cnblogs.com/mxjhaima/p/15423103.html
Copyright © 2020-2023  润新知