leetcode-40场双周赛

5557. 最大重复子字符串

题目-5557. 最大重复子字符串
比赛的时候写的超级复杂,最简单的就是一次构造k个重复的word,查查有没有。

class Solution {
    public int maxRepeating(String sequence, String word) {
        int cnt = 0;
        String ss = word;
        int n  = sequence.length();
        int m = word.length();
        while (true){
            if (ss.length() > n){
                break;
            }
            if (sequence.contains(ss)){
                cnt++;
                ss = ss + word;
            }
            else{
                break;
            }
        }
        return cnt;

    }
}

5558. 合并两个链表

题目-5558. 合并两个链表
获取list1截取位置的前一个节点和后一个节点,list2的最后一个节点,连接即可。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode mergeInBetween(ListNode list1, int a, int b, ListNode list2) {
        ListNode cur1 = list1, cur11 = list1, cur2 = list2;
        while (cur2.next != null){
            cur2 = cur2.next;
        }
        int cnt = 0;
        while (cnt < a - 1){
            cur1 = cur1.next;
            cnt++;
        }
        cnt = 0;
        while (cnt <= b){
            cur11 = cur11.next;
            cnt++;
        }
        cur1.next = list2;
        cur2.next = cur11;
        return list1;
        
    }
}

5560. 设计前中后队列

题目-5560. 设计前中后队列
维持一个ArrayList,按照要求修改即可

class FrontMiddleBackQueue {
    private List<Integer> arr = new ArrayList<>();
    public FrontMiddleBackQueue() {

    }
    
    public void pushFront(int val) {
        arr.add(0, val);
    }
    
    public void pushMiddle(int val) {
        arr.add(arr.size() / 2, val);
    }
    
    public void pushBack(int val) {
        arr.add(arr.size(), val);
    }
    
    public int popFront() {
        if (arr.isEmpty()) return -1;
        int val = arr.get(0);
        arr.remove(0);
        return val;
    }
    
    public int popMiddle() {
        if (arr.isEmpty()) return -1;
        int val = arr.get((arr.size() - 1) / 2);
        arr.remove((arr.size() - 1) / 2);
        return val;
    }
    
    public int popBack() {
        if (arr.isEmpty()) return -1;
        int val = arr.get(arr.size() - 1);
        arr.remove(arr.size() - 1);
        return val;
    }
}

/**
 * Your FrontMiddleBackQueue object will be instantiated and called as such:
 * FrontMiddleBackQueue obj = new FrontMiddleBackQueue();
 * obj.pushFront(val);
 * obj.pushMiddle(val);
 * obj.pushBack(val);
 * int param_4 = obj.popFront();
 * int param_5 = obj.popMiddle();
 * int param_6 = obj.popBack();
 */

当然也可以作死,自己去维护一个数组

class FrontMiddleBackQueue {
    private int[] arr = new int[1005];
    private int length = 0;

    public FrontMiddleBackQueue() {
        this.length = 0;
    }
    
    public void pushFront(int val) {
        for (int i = length; i >= 1; i--){
            arr[i] = arr[i - 1];
        }
        arr[0] = val;
        length+=1;
    }
    
    public void pushMiddle(int val) {
        int x = length / 2;
        for (int i = length; i > x; i--){
            arr[i] = arr[i - 1];
        }
        arr[x] = val;
        length+=1;
    }
    
    public void pushBack(int val) {
        arr[length] = val;
        length ++;
        
    }
    
    public int popFront() {
        if (length > 0){
            int x = arr[0];
            for (int i = 1; i < length; i++){
                arr[i - 1] = arr[i];
            }
            length--;
            return x;
        }
        else{
            return -1;
        }
    }
    
    public int popMiddle() {
        if (length <= 0) return -1;
        int x = arr[(length - 1) / 2];
        for (int i = (length-1) / 2 ; i < length-1; i++){
            arr[i] = arr[i+1];
        }
        length--;
        return x;
    }
    
    public int popBack() {
        if (length <=0) return -1;
        length--;
        return arr[length];
    }
}

/**
 * Your FrontMiddleBackQueue object will be instantiated and called as such:
 * FrontMiddleBackQueue obj = new FrontMiddleBackQueue();
 * obj.pushFront(val);
 * obj.pushMiddle(val);
 * obj.pushBack(val);
 * int param_4 = obj.popFront();
 * int param_5 = obj.popMiddle();
 * int param_6 = obj.popBack();
 */

再更:这题更优的做法,应该是维护两个双端链表,第一个链表存储0~mid, 第二个存储mid+1 ~ end
这样,在每次添加时,需要额外进行一次检查,来调整left和right的平衡,时间开销为O(1),这样即可将查询中间的时间复杂度从O(n)降至O(1)

class FrontMiddleBackQueue {
    private LinkedList<Integer> left;
    private LinkedList<Integer> right;
    
    public FrontMiddleBackQueue() {
        left = new LinkedList<>();
        right = new LinkedList<>();
    }
    
    public void pushFront(int val) {
        left.addFirst(val);
        check();
    }
    
    public void pushMiddle(int val) {
        if (left.size() - right.size() == 1){
            int t = left.peekLast();
            left.removeLast();
            right.addFirst(t);
        }
        left.addLast(val);
        check();
    }
    
    public void pushBack(int val) {
        right.addLast(val);
        check();
    }
    
    public int popFront() {
        if (left.size() == 0 && right.size() == 0) return -1;
        int val = left.peek();
        left.removeFirst();
        check();
        return val;
    }
    
    public int popMiddle() {
        if (left.size() == 0 && right.size() == 0) return -1;
        int val = left.peekLast();
        left.removeLast();
        check();
        return val;
    }
    
    public int popBack() {
        if (left.size() == 0 && right.size() == 0) return -1;
        int val = -1;
        if (right.size() == 0){
            val = left.peekLast();
            left.removeLast();
        }
        else{
            val = right.peekLast();
            right.removeLast();
        }
        check();
        return val;
    }

    private void check(){
        if (left.size() - right.size() > 1){
            int t = left.peekLast();
            left.removeLast();
            right.addFirst(t);
        }
        else if (right.size() > left.size()){
            int t = right.peekFirst();
            right.removeFirst();
            left.add(t);
        }
    }
}

/**
 * Your FrontMiddleBackQueue object will be instantiated and called as such:
 * FrontMiddleBackQueue obj = new FrontMiddleBackQueue();
 * obj.pushFront(val);
 * obj.pushMiddle(val);
 * obj.pushBack(val);
 * int param_4 = obj.popFront();
 * int param_5 = obj.popMiddle();
 * int param_6 = obj.popBack();
 */

5559. 得到山形数组的最少删除次数

题目-5559. 得到山形数组的最少删除次数
求最长上升子序列长度的变种,维护两个数组,一个计算当前点左边有多少比他低的,另一个计算当前点右边有多少比他低的。最后,左右求和取最大。注意,i必须大于0.

class Solution {
    public int minimumMountainRemovals(int[] nums) {
        int n = nums.length;
        int[] dppre = new int[n + 1];
        int[] dplast = new int[n + 1];
        dppre[0] = 0;
        dplast[n - 1] = 0;
        for (int i = 1; i < n; i++){
            for (int j = 0; j < i; j++){
                if (nums[j] < nums[i]){
                    dppre[i] = Math.max(dppre[i], dppre[j] + 1);
                }
            }
        }
        
        for (int i = n - 2; i >= 0; i--){
            for (int j = n - 1; j > i; j--){
                if (nums[i] > nums[j]){
                    dplast[i] = Math.max(dplast[i], dplast[j] + 1);
                }
            }
        }
        
        int maxx = 0;
        for (int i = 0; i < n; i++){
            if (dppre[i] + dplast[i] > maxx){
                if (dppre[i]>0 && dplast[i] >0)
                    maxx = dppre[i] + dplast[i];
            }
        }
        return n - maxx - 1;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值