Loading...

学习更新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;

    }
}
posted @ 2021-10-19 01:20  梦想家haima  阅读(42)  评论(0编辑  收藏  举报