代码随想录算法训练营周末二

发布于:2025-04-09 ⋅ 阅读:(29) ⋅ 点赞:(0)

其他:
今日总结
往期打卡


3502. 到达每个位置的最小费用

跳转: 3502. 到达每个位置的最小费用

问题:

给你一个长度为 n 的整数数组 cost 。当前你位于位置 n(队伍的末尾),队伍中共有 n + 1 人,编号从 0 到 n

你希望在队伍中向前移动,但队伍中每个人都会收取一定的费用才能与你 交换位置。与编号 i 的人交换位置的费用为 cost[i]

你可以按照以下规则与他人交换位置:

  • 如果对方在你前面,你 必须 支付 cost[i] 费用与他们交换位置。
  • 如果对方在你后面,他们可以免费与你交换位置。

返回一个大小为 n 的数组 answer,其中 answer[i] 表示到达队伍中每个位置 i 所需的 最小 总费用。
在这里插入图片描述

思路:

到达每个位置的最小费用就是在包含了自身的前缀中取最小值,所以只需维护当前最小值逐位存储即可

复杂度:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

代码:

class Solution {
    public int[] minCosts(int[] cost) {
        int min = cost[0];
        int[] res = new int[cost.length];
        res[0] = min;
        for(int i=1;i<cost.length;i++){
            if(cost[i]<min){
                min = cost[i];
            }
            res[i] = min;
        }
        return res;
    }
}

718. 最长重复子数组

跳转: 718. 最长重复子数组

问题:

给两个整数数组 nums1nums2 ,返回 两个数组中 公共的 、长度最长的子数组的长度
在这里插入图片描述

思路:

动态规划.
比较容易理解的一种递推方式是增加前缀,前缀能匹配就是后一个的最大前缀数+1,不匹配就归零.
或者也可以顺着思考,拿一个和另一个做比较,只记连续的数量,断开就要清零.

复杂度:

  • 时间复杂度: O ( n ∗ m ) O(n*m) O(nm)
  • 空间复杂度: O ( m i n ( m , n ) ) O(min(m,n)) O(min(m,n))

代码:

class Solution {
    public int findLength(int[] nums1, int[] nums2) {
        if (nums1.length > nums2.length) {
            int[] temp = nums1;
            nums1 = nums2;
            nums2 = temp;
        }
        int n = nums1.length;
        int m = nums2.length;
        int ans = 0;
        int[] fn = new int[m+1];
        for(int i=0;i<n;i++){
            for(int j=m-1;j>=0;j--){
                fn[j+1] = nums1[i]==nums2[j]?fn[j]+1:0;
                ans = Math.max(ans,fn[j+1]);
            }
        }
        return ans;
    }
}

3507. 移除最小数对使数组有序 I

跳转: 3507. 移除最小数对使数组有序 I

问题:

给你一个数组 nums,你可以执行以下操作任意次数:

  • 选择 相邻 元素对中 和最小 的一对。如果存在多个这样的对,选择最左边的一个。
  • 用它们的和替换这对元素。

返回将数组变为 非递减 所需的 最小操作次数

如果一个数组中每个元素都大于或等于它前一个元素(如果存在的话),则称该数组为非递减
在这里插入图片描述

思路:

暴力模拟,在判断时记录最小位置,方便合并操作.
min不能开太小,太小了有可能多数合并超过min

复杂度:

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( n ) O(n) O(n)

代码:

class Solution {
    int min = 50001;
    int start=0;
    public int minimumPairRemoval(int[] nums) {
        int count = 0;
        while(!isNonDecreasing(nums)){
            count+=1;
            nums = getMerge(nums);
            // System.out.println(Arrays.toString(nums));
        }
        return count;
    }
    boolean isNonDecreasing(int[] nums){
        boolean res = true;
        for(int i=1;i<nums.length;i++){
            if(nums[i]<nums[i-1]) res = false;
            int tmp = nums[i]+nums[i-1];
            if(tmp<min){
                min = tmp;
                start = i-1;
            }
        }
        return res;
    }
    int[] getMerge(int[]nums){
        int[] res = new int[nums.length-1];
        int j = 0;
        for(int i=0;i<nums.length&&j<nums.length-1;i++){
            if(i==start){
                res[j++] = min;
                min = 50001;
                i++;
            }
            else res[j++] = nums[i];
        }
        return res;
    }
}

368. 最大整除子集(每日一题)

跳转: 368. 最大整除子集

问题:

给你一个由 无重复 正整数组成的集合 nums ,请你找出并返回其中最大的整除子集 answer ,子集中每一元素对 (answer[i], answer[j]) 都应当满足:

  • answer[i] % answer[j] == 0 ,或
  • answer[j] % answer[i] == 0

如果存在多个有效解子集,返回其中任何一个均可。
在这里插入图片描述

思路:

先排序,方便判断余数
状态变量的含义为以当前元素结尾的整除子集的数量
记录好最大状态,然后遍历状态数组求出一个有效子集即可

复杂度:

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( n ) O(n) O(n)

代码:

class Solution {
    public List<Integer> largestDivisibleSubset(int[] nums) {
        int n = nums.length;
        Arrays.sort(nums);
        int[] fn = new int[n];
        Arrays.fill(fn, 1);
        int max = 1;
        int maxValue=0;
        for (int i = 1; i < n; i++) {
            for (int k = i - 1; k >= 0; k--) {
                if (nums[i] % nums[k] == 0) {
                    fn[i] = Math.max(fn[i], fn[k] + 1);
                }
            }
            if (fn[i] > max) {
                max = Math.max(max, fn[i]);
                maxValue = nums[i];
            }
        }
        // System.out.println(max);

        List<Integer> res = new ArrayList<>();
        for(int i=n-1;i>=0&&max>0;i--){
            if(fn[i]==max&&maxValue%nums[i]==0){
                maxValue = nums[i];
                res.add(nums[i]);
                max--;
            }
        }
        return res;
    }
}

5. 最长回文子串

跳转: 5. 最长回文子串

问题

给你一个字符串 s,找到 s 中最长的 回文 子串。
在这里插入图片描述

思路:

遍历字符串长度和初值,并特判长度为3以内的情况,记录最大值的长度和初值直接返回子串

复杂度:

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( n ) O(n) O(n)

代码:

class Solution {
    public String longestPalindrome(String s) {
        int n = s.length();
        boolean[][] dp = new boolean[n+1][n];
        int max = 1;
        int begin = 0;
        Arrays.fill(dp[1],true);
        for(int i=2;i<=n;i++){
            for(int j=0;j<=n-i;j++){
                int e = j+i-1;
                if(s.charAt(j)==s.charAt(e))
                    if(i<3){
                        dp[i][j] = true;
                    }else{
                        dp[i][j] = dp[i-2][j+1];
                    }
                else dp[i][j] = false;
                if(dp[i][j]&&i>max){
                    max = i;
                    begin = j;
                }
            }
        }
        return s.substring(begin,begin+max);
    }
}

总结

今天去试了一下周赛,就做出了一个,第二题用哈希加遍历统计就直接超时了
做了一些动态规划的题目,感觉对动态规划的题目不够熟练

往期打卡

代码随想录算法训练营第一天

代码随想录算法训练营第二天

代码随想录算法训练营第三天

代码随想录算法训练营第四天

代码随想录算法训练营周末一

代码随想录算法训练营第五天

代码随想录算法训练营第六天

代码随想录算法训练营第七天

代码随想录算法训练营第八天

代码随想录算法训练营第九天

代码随想录算法训练营第十天


网站公告

今日签到

点亮在社区的每一天
去签到