• [Leetcode Weekly Contest]272


    链接:LeetCode

    [Leetcode]2108. 找出数组中的第一个回文字符串

    给你一个字符串数组 words ,找出并返回数组中的 第一个回文字符串 。如果不存在满足要求的字符串,返回一个 空字符串 "" 。

    回文字符串 的定义为:如果一个字符串正着读和反着读一样,那么该字符串就是一个 回文字符串 。

    遍历即可。

    class Solution {
         private boolean isPalindrome(String word) {
             int start = 0, end = word.length()-1;
             while(start < end) {
                 if(word.charAt(start++) != word.charAt(end--)) {
                     return false;
                 }
             }
             return true;
         }
    
        public String firstPalindrome(String[] words) {
            for(var word:words) {
                if(isPalindrome(word)) return word;
            }
            return "";
        }
    }
    

    [Leetcode]2109. 向字符串添加空格

    给你一个下标从 0 开始的字符串 s ,以及一个下标从 0 开始的整数数组 spaces 。

    数组 spaces 描述原字符串中需要添加空格的下标。每个空格都应该插入到给定索引处的字符值 之前 。

    例如,s = "EnjoyYourCoffee" 且 spaces = [5, 9] ,那么我们需要在 'Y' 和 'C' 之前添加空格,这两个字符分别位于下标 5 和下标 9 。因此,最终得到 "Enjoy Your Coffee" 。
    请你添加空格,并返回修改后的字符串。

    暴力循环即可。注意拼接String可以用StringBuilder。

    class Solution {
        public String addSpaces(String s, int[] spaces) {
            int n = s.length();
            int sn = spaces.length;
    
            StringBuilder SB = new StringBuilder();
            int si = 0;
            int cnt = -1;
            for (int i = 0; i < n; i ++)
            {
                cnt ++;
                if (si < sn && cnt == spaces[si])
                {
                    SB.append(' ');
                    si ++;
                }
                SB.append(s.charAt(i));
            }
            return SB.toString();
        }
    }
    

    [Leetcode]2110. 股票平滑下跌阶段的数目

    给你一个整数数组 prices ,表示一支股票的历史每日股价,其中 prices[i] 是这支股票第 i 天的价格。

    一个 平滑下降的阶段 定义为:对于 连续一天或者多天 ,每日股价都比 前一日股价恰好少 1 ,这个阶段第一天的股价没有限制。

    请你返回 平滑下降阶段 的数目。

    动态规划,如果是平滑阶段就累加上一次的状态,否则就为1。

    class Solution {
         public long getSubDesent(double steps)
         {
             return (long)(steps / 2. * (steps-1));
         }
    
        public long getDescentPeriods(int[] prices) {
            int step = 1;
            long res = prices.length;
            for(int ind = 1; ind < prices.length; ind ++) {
                if(prices[ind] == prices[ind-1] - 1) step ++;
                else {
                    res += getSubDesent(step);
                    step = 1;
                }
            }
            if(step > 1) res += getSubDesent(step);
            return res;
        }
    }
    

    [Leetcode]2111. 使数组 K 递增的最少操作次数

    给你一个下标从 0 开始包含 n 个正整数的数组 arr ,和一个正整数 k 。

    如果对于每个满足 k <= i <= n-1 的下标 i ,都有 arr[i-k] <= arr[i] ,那么我们称 arr 是 K 递增 的。

    比方说,arr = [4, 1, 5, 2, 6, 2] 对于 k = 2 是 K 递增的,因为:
    arr[0] <= arr[2] (4 <= 5)
    arr[1] <= arr[3] (1 <= 2)
    arr[2] <= arr[4] (5 <= 6)
    arr[3] <= arr[5] (2 <= 2)
    但是,相同的数组 arr 对于 k = 1 不是 K 递增的(因为 arr[0] > arr[1]),对于 k = 3 也不是 K 递增的(因为 arr[0] > arr[3] )。
    每一次 操作 中,你可以选择一个下标 i 并将 arr[i] 改成任意 正整数。
    请你返回对于给定的 k ,使数组变成 K 递增的 最少操作次数 。

    分组+二分 O(NlogN)。
    两个难点,第一个是想到求最长递增子序列。对于给定的一个序列,如果我们希望通过修改最少的元素,使得它单调递增,那么最少需要修改的元素个数,就是「序列的长度」减去「序列的最长递增子序列」的长度。
    第二个是怎么求序列的最长非严格递增子序列。参考最长递增子序列, 不同的是,我们在求非严格递增子序列长度的时候,假设遍历的值为target,则二分需要找到严格大于target的值。想象这样一个例子:3331112,在循环中,如果我们替换大于等于target的值最后会出现123,无法得出长度为4的结论,理由是我们在每次加入1的时候没有替换到3的位置。相通这一点,整个算法也就很好算了。

    class Solution {
        public int kIncreasing(int[] arr, int k) {
            int res = 0;
            if(k >= arr.length) return res;
            List<ArrayList<Integer>> subArray = new ArrayList<>(k);
            for(int ind=0;ind<arr.length;ind++){
                if(ind < k) subArray.add(new ArrayList<Integer>());
                int index = ind % k;
                subArray.get(index).add(arr[ind]);
            }
            for(var list:subArray) {
                res += getMinOperation(list);
            }
            return res;
        }
    
        private int getMinOperation(List<Integer> list) {
            List<Integer> stack = new ArrayList<>();
            int res = 0;
            for(int i=0;i<list.size();++i) {
                int target = list.get(i);
                if(stack.isEmpty() || target>=stack.get(stack.size()-1)) stack.add(target);
                else stack.set(getFirstLargerIndex(stack, target), target);
            }
            return list.size() - stack.size();
        }
    
        private int getFirstLargerIndex(List<Integer> nums, int target) {
            int lo = 0, hi = nums.size()-1;
            while(lo <= hi) {
                int mid = lo+(hi-lo)/2;
                if(nums.get(mid) <= target) lo = mid + 1;
                else hi = mid - 1;
            }
            return lo;
        }
    }
    

    Leetcode

  • 相关阅读:
    (转) 网络流之最大流算法(EdmondsKarp)
    如何在面试中发现优秀程序员
    Java中Volatile关键字详解
    比AtomicLong还高效的LongAdder 源码解析
    AtomicInteger的用法
    synchronized详解
    Java内部锁的可重用性(Reentrancy)
    Java可重入锁
    关于原生javascript的this,this真是个强大的东东
    js时间戳怎么转成日期格式
  • 原文地址:https://www.cnblogs.com/hellojamest/p/16197728.html
Copyright © 2020-2023  润新知