210626 双周赛

1909.删除一个元素使数组严格递增

题目描述

给你一个下标从 0 开始的整数数组 nums ,如果 恰好 删除 一个 元素后,数组 严格递增 ,那么请你返回 true ,否则返回 false 。如果数组本身已经是严格递增的,请你也返回 true 。
数组 nums 是 严格递增 的定义为:对于任意下标的 1 <= i < nums.length 都满足 nums[i - 1] < nums[i] 。

示例 1:

输入:nums = [1,2,10,5,7]
输出:true
解释:从 nums 中删除下标 2 处的 10 ,得到 [1,2,5,7] 。
[1,2,5,7] 是严格递增的,所以返回 true 。

示例 2:

输入:nums = [2,3,1,2]
输出:false
解释:
[3,1,2] 是删除下标 0 处元素后得到的结果。
[2,1,2] 是删除下标 1 处元素后得到的结果。
[2,3,2] 是删除下标 2 处元素后得到的结果。
[2,3,1] 是删除下标 3 处元素后得到的结果。
没有任何结果数组是严格递增的,所以返回 false 。

示例 3:

输入:nums = [1,1,1]
输出:false
解释:删除任意元素后的结果都是 [1,1] 。
[1,1] 不是严格递增的,所以返回 false 。

示例 4:

输入:nums = [1,2,3]
输出:true
解释:[1,2,3] 已经是严格递增的,所以返回 true 。

解答

解1

自己的解法,不是很简洁
思路:找到不递增的两个数,若需要满足答案的条件,则必须删除一个,此时分两种情况判断删除后是否达成条件(删除前一个或删除后一个),若两种情况都不行,则返回false,两种有一种成功了,返回true
o(n^2)

class Solution {
    public boolean canBeIncreasing(int[] nums) {
        if(isTrue(nums,-1)){
            return true;
        }
        for(int i = 1;i < nums.length;i++){
            if(nums[i] <= nums[i - 1]){
                if(isTrue(nums,i) || isTrue(nums,i - 1)){
                    return true;
                }else{
                    return false;
                }
            }
        }
        return true;

    }
    public boolean isTrue(int[] nums,int index){

        for(int i = 1;i < nums.length;i++){
            if(index != -1){
                if(i == index){
                    continue;
                }else if(i - 1 == index && i == 1){
                    continue;
                }else if(i - 1 == index){
                    if(nums[i] <= nums[i - 2]){
                        return false;
                    }
                }else{
                    if(nums[i] <= nums[i - 1]){
                        return false;
                    }
                }
            }else{
                if(nums[i] <= nums[i - 1]){
                    return false;
                }
            }
            
        }
        return true;
    }
}

解2

贪心
找到不一样的,判断需要删除i还是i-1即可
如果删除nums[i] nums[i] = nums[i - 1]
如果删除nums[i - 1] nums[i - 1] = nums[i]
一次遍历 o(n)

class Solution {
    public boolean canBeIncreasing(int[] nums) {
        int cnt = 0;
        for (int i = 1; i < nums.length && cnt <= 1; i++) {
        if (nums[i] > nums[i - 1]) continue;         
        cnt++;
        if (i - 1 > 0 && nums[i] <= nums[i - 2]) {   
            nums[i] = nums[i - 1];
        } else {
            nums[i - 1] = nums[i];
        }
        }
        return cnt <= 1;
    }
}

1910. 删除一个字符串中所有出现的给定子字符串

题目描述

给你两个字符串 s 和 part ,请你对 s 反复执行以下操作直到 所有 子字符串 part 都被删除:

  • 找到 s 中 最左边 的子字符串 part ,并将它从 s 中删除。
    请你返回从 s 中删除所有 part 子字符串以后得到的剩余字符串。
  • 一个 子字符串 是一个字符串中连续的字符序列。

示例 1:

输入:s = “daabcbaabcbc”, part = “abc”
输出:“dab”
解释:以下操作按顺序执行:
s = “daabcbaabcbc” ,删除下标从 2 开始的 “abc” ,得到 s = “dabaabcbc” 。
s = “dabaabcbc” ,删除下标从 4 开始的 “abc” ,得到 s = “dababc” 。
s = “dababc” ,删除下标从 3 开始的 “abc” ,得到 s = “dab” 。
此时 s 中不再含有子字符串 “abc” 。

示例 2:

输入:s = “axxxxyyyyb”, part = “xy”
输出:“ab”
解释:以下操作按顺序执行:
s = “axxxxyyyyb” ,删除下标从 4 开始的 “xy” ,得到 s = “axxxyyyb” 。
s = “axxxyyyb” ,删除下标从 3 开始的 “xy” ,得到 s = “axxyyb” 。
s = “axxyyb” ,删除下标从 2 开始的 “xy” ,得到 s = “axyb” 。
s = “axyb” ,删除下标从 1 开始的 “xy” ,得到 s = “ab” 。
此时 s 中不再含有子字符串 “xy” 。

提示:
1 <= s.length <= 1000
1 <= part.length <= 1000
s​​​​​​ 和 part 只包小写英文字母。

解答

解1

StringBuilder

class Solution {
    public String removeOccurrences(String s, String part) {
        StringBuilder sb = new StringBuilder(s);
        while(sb.indexOf(part) != -1){
            int index = sb.indexOf(part);
            sb.delete(index,index + part.length());
        }
        return sb.toString();
    }
}

1911. 最大子序列交替和

题目描述

一个下标从 0 开始的数组的 交替和 定义为 偶数 下标处元素之 和 减去 奇数 下标处元素之 和 。
比方说,数组 [4,2,5,3] 的交替和为 (4 + 5) - (2 + 3) = 4 。
给你一个数组 nums ,请你返回 nums 中任意子序列的 最大交替和 (子序列的下标 重新 从 0 开始编号)。
一个数组的 子序列 是从原数组中删除一些元素后(也可能一个也不删除)剩余元素不改变顺序组成的数组。比方说,[2,7,4] 是 [4,2,3,7,2,1,4] 的一个子序列(加粗元素),但是 [2,4,2] 不是。

示例 1:

输入:nums = [4,2,5,3]
输出:7
解释:最优子序列为 [4,2,5] ,交替和为 (4 + 5) - 2 = 7 。

示例 2:

输入:nums = [5,6,7,8]
输出:8
解释:最优子序列为 [8] ,交替和为 8 。

示例 3:

输入:nums = [6,2,1,2,4,5]
输出:10
解释:最优子序列为 [6,1,5] ,交替和为 (6 + 5) - 1 = 10 。

提示:
1 <= nums.length <= 105
1 <= nums[i] <= 105

解答

解1

畅游面试中的动态规划套路

DP状态机
状态定义:

  • f[i][0]:前i个数中选中偶数个数的最大交替和
  • f[i][0]:前i个数中选中奇数个数的最大交替和
class Solution {
    public long maxAlternatingSum(int[] nums) {
        int l = nums.length;
        long[][] dp = new long[l + 1][2];
        for(int i = 0;i <= l;i++){
        	//防止溢出
            Arrays.fill(dp[i],Integer.MIN_VALUE >> 1);
        }
        dp[0][0] = 0;
        for(int i = 1;i <= l;i++){
        	//前i个数的偶数个数交替最大值,从奇数个数个的交替最大和中转移
            dp[i][0] = Math.max(dp[i - 1][0],dp[i - 1][1] - nums[i - 1]);
            //同理
            dp[i][1] = Math.max(dp[i - 1][1],dp[i - 1][0] + nums[i - 1]);
        }
        return Math.max(dp[l][1],dp[l][0]);
    }
}

解2

解一定是奇数个值
找到第一个最大值,然后两两对比判断是否为正收益(nums[i] > nums[i - 1]),是,就加入,不是,找下一组

class Solution {
    public long maxAlternatingSum(int[] nums) {
        long first = nums[0];
        int index = 1;
        while(index < nums.length){
            if(nums[index] > first){
                first = nums[index];
                index++;
            }else{
                break;
            }
        }
        if(index == nums.length){
            return first;
        }
        long res = first;
        index++;
        while(index < nums.length){
            if(nums[index] > nums[index - 1]){
                res += nums[index] - nums[index - 1];
            }
            index++;
        }
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值