leetcode刷题笔记(10)

(1)321. 拼接最大数(错1)

题解思路:

class Solution {
    public int[] maxNumber(int[] nums1, int[] nums2, int k) {
        int m = nums1.length, n = nums2.length;
        int[] maxSubsequence = new int[k];
        int start = Math.max(0, k - n), end = Math.min(k, m);
        for (int i = start; i <= end; i++) {
            int[] subsequence1 = maxSubsequence(nums1, i);
            int[] subsequence2 = maxSubsequence(nums2, k - i);
            int[] curMaxSubsequence = merge(subsequence1, subsequence2);
            if (compare(curMaxSubsequence, 0, maxSubsequence, 0) > 0) {
                System.arraycopy(curMaxSubsequence, 0, maxSubsequence, 0, k);
            }
        }
        return maxSubsequence;
    }
*****************************************************
    public int[] maxSubsequence(int[] nums, int k) {
        int length = nums.length;
        int[] stack = new int[k];
        int top = -1;
        int remain = length - k;
        for (int i = 0; i < length; i++) {
            int num = nums[i];
            while (top >= 0 && stack[top] < num && remain > 0) {
                top--;
                remain--;
            }
            if (top < k - 1) {
                stack[++top] = num;
            } else {
                remain--;
            }
        }
        return stack;
    }
    ********************************************************

    public int[] merge(int[] subsequence1, int[] subsequence2) {
        int x = subsequence1.length, y = subsequence2.length;
        if (x == 0) {
            return subsequence2;
        }
        if (y == 0) {
            return subsequence1;
        }
        int mergeLength = x + y;
        int[] merged = new int[mergeLength];
        int index1 = 0, index2 = 0;
        for (int i = 0; i < mergeLength; i++) {
            if (compare(subsequence1, index1, subsequence2, index2) > 0) {
                merged[i] = subsequence1[index1++];
            } else {
                merged[i] = subsequence2[index2++];
            }
        }
        return merged;
    }

    public int compare(int[] subsequence1, int index1, int[] subsequence2, int index2) {
        int x = subsequence1.length, y = subsequence2.length;
        while (index1 < x && index2 < y) {
            int difference = subsequence1[index1] - subsequence2[index2];
            if (difference != 0) {
                return difference;
            }
            index1++;
            index2++;
        }
        return (x - index1) - (y - index2);
    }
}

(2)76. 最小覆盖子串(错1)

题解思路:双指针滑动窗口法,使用一个map:need来记录需要各个字符的个数;使用一个map:window记录窗口中已有的字符数,left,right是窗口起始指针,start是记录当前len最小的覆盖子串的开始位置,valid记录已经满足的字符数量;
注意:Integer会缓存频繁使用的数值,数值分为是-128-127;在范围内直接返回缓存值,超过范围new一个对象,所以需要在进行比较时,在get().intValue();

class Solution {
    public String minWindow(String s, String t) {
        HashMap<Character, Integer> need = new HashMap<Character, Integer>();
        HashMap<Character, Integer> window = new HashMap<Character, Integer>();
        for(char c : t.toCharArray()){
            need.put(c, need.getOrDefault(c, 0) + 1);
        }

        int left = 0;
        int right = 0;
        int valid = 0;
        int start = 0;
        int len = Integer.MAX_VALUE;

        while(right < s.length()){
            char c = s.charAt(right);
            right++;
            if(need.getOrDefault(c, 0) > 0){
                window.put(c, window.getOrDefault(c, 0) + 1);
                if(window.getOrDefault(c, 0).intValue() == need.getOrDefault(c, 0).intValue()){
                    valid++;
                }
            }
            while(valid == need.size()){
                if(right - left < len){
                    start = left;
                    len = right - left;
                }
                char d = s.charAt(left);
                left++;
                if(need.getOrDefault(d, 0) > 0){
                    if(window.get(d).intValue() == need.get(d).intValue()){
                        valid--;
                    }
                    window.put(d,window.getOrDefault(d, 0) - 1);
                }
            }
        }
        return len == Integer.MAX_VALUE ? "" : s.substring(start,start+len);
    }
}

python

class Solution:
    def minWindow(self, s: str, t: str) -> str:
        mem = defaultdict(int)
        for char in t:
        	mem[char]+=1
        t_len = len(t)

        minLeft, minRight = 0,len(s)
        left = 0

        for right,char in enumerate(s):
        	if mem[char]>0:
        		t_len-=1
        	mem[char]-=1

        	if t_len==0:
        		while mem[s[left]]<0:
        			mem[s[left]]+=1
        			left+=1

        		if right-left<minRight-minLeft:
        			minLeft,minRight = left,right

        		mem[s[left]]+=1
        		t_len+=1
        		left+=1
        return '' if minRight==len(s) else s[minLeft:minRight+1] 

滑动窗口算法框架:

HashMap<Character, Integer> need = new HashMap<Character,Integer>();
HashMap<Character, Integer> window = new HashMap<Character,Integer>();
for(char c : t.toCharArray()){
        need.put(c, need.getOrDefault(c, 0) + 1);
}

int left = 0;
int right = 0;
int valid = 0;
while(right < s.length()){
	//要移入的字符
	char c = s.charAt(right);
	right++;
	***一系列更新
//判断左窗口是否要收缩
	while(window needs shrink){
		//要移出的字符
		char d = s.charAt(left);
		left++;
		***一系列更新
		}
}

(3)567. 字符串的排列

思路:滑动窗口法,对于新加入的字符有三种情况:(1)是s1中的,且当前窗口中该字符的数量小于s1中的数量,那么添加到窗口中;(2)不是s1中的字符,从下一个字符重新搜索;(3)是s1中的字符,但当前窗口中已经有足够数量的该字符,那么先将该字符加入窗口中,再从left位置出发,将一个相同字符前出现的字符移出窗口。

class Solution {
    public boolean checkInclusion(String s1, String s2) {
        HashMap<Character, Integer> need = new HashMap<Character, Integer>();
        HashMap<Character, Integer> window = new HashMap<Character, Integer>();
        for(char c: s1.toCharArray()){
            need.put(c, need.getOrDefault(c, 0) + 1);
        }
        int left = 0;
        int right = 0;
        int valid = 0;
        while(right < s2.length()){
            char c = s2.charAt(right);
            right++;
            if(window.getOrDefault(c, 0) < need.getOrDefault(c,0)){
                window.put(c, window.getOrDefault(c, 0) + 1);
                if(window.get(c).intValue() == need.get(c).intValue()){
                    valid++;
                }
                if(valid == need.size()){
                    return true;
                }
            }else if(need.getOrDefault(c,0) == 0){
                window = new HashMap<Character, Integer>();
                valid = 0;
                left = right;
            }else{
                window.put(c, window.getOrDefault(c, 0) + 1);
                while(window.get(c).intValue() > need.get(c).intValue()){
                    char d = s2.charAt(left);
                    left++;
                    if(window.get(d).intValue() == need.get(d).intValue()){
                        valid--;
                    }
                    window.put(d, window.get(d)-1);
                }
            }
        }
        return false;
    }
}

(4)438. 找到字符串中所有字母异位词

思路:滑动窗口

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        HashMap<Character, Integer> need = new HashMap<Character,Integer>();
        HashMap<Character, Integer> window = new HashMap<Character,Integer>();
        for(char c: p.toCharArray()){
            need.put(c, need.getOrDefault(c, 0) + 1);
        }
        int left = 0;
        int right = 0;
        int valid = 0;
        List<Integer> res = new ArrayList<Integer>();
        while(right < s.length()){
            char c = s.charAt(right);
            right++;
            if(window.getOrDefault(c, 0) <= need.getOrDefault(c, 0)){
                window.put(c, window.getOrDefault(c, 0) + 1);
                if(window.getOrDefault(c,0).intValue() == need.getOrDefault(c,0).intValue()){
                    valid++;
                }
                while(valid == need.size()){
                    res.add(left);
                    char d = s.charAt(left);
                    left++;
                    if(window.getOrDefault(d,0).intValue() == need.getOrDefault(d,0).intValue()){
                        valid--;
                    }
                    window.put(d, window.get(d) - 1);
                }
            }else if(need.getOrDefault(c,0) == 0){
                left = right;
                window = new HashMap<Character,Integer>();
                valid = 0;
                continue;
            }
            while(window.getOrDefault(c,0) > need.getOrDefault(c,0)){
                char d = s.charAt(left);
                left++;
                if(window.getOrDefault(d,0).intValue() == need.getOrDefault(d,0).intValue()){
                    valid--;
                }
                window.put(d, window.get(d) - 1);
            }
        }
        return res;
    }
}

(5)334. 递增的三元子序列(错1)

题解思路:贪心算法,用a记录当前遍历到的最小数字,b记录第二小数字,如果找到比a,b都大的数字,则返回true

class Solution {
    public boolean increasingTriplet(int[] nums) {
        if(nums.length < 3){
            return false;
        }
        int a = Integer.MAX_VALUE;
        int b = Integer.MAX_VALUE;

        for(int i = 0; i < nums.length; i++){
            if(nums[i] <= a){
                a = nums[i];
            }else if(nums[i] <= b){
                b = nums[i];
            }else{
                return true;
            }
        }
        return false;
    }
}

(6)121. 买卖股票的最佳时机

class Solution {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        if(len < 2){
            return 0;
        }
        int[][] dp = new int[len+1][2];
        dp[0][0] = 0;
        dp[0][1] = Integer.MIN_VALUE;
        for(int i = 1; i <= len; i++){
            dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1]+prices[i-1]);
            dp[i][1] = Math.max(dp[i-1][1],-prices[i-1]);
        }
        return dp[len][0];
    }
}

(7)122. 买卖股票的最佳时机 II

class Solution {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        int[][] dp = new int[len+1][2];
        dp[0][0] = 0;
        dp[0][1] = Integer.MIN_VALUE;
        for(int i = 1; i <= len; i++){
            dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] + prices[i-1]);
            dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0] - prices[i-1]);
        }
        return dp[len][0];
    }
}

(8)123. 买卖股票的最佳时机 III

class Solution {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        int[][][] dp = new int[len+1][3][2];

        for(int i = 0; i < 3; i++){
            dp[0][i][0] = 0;
            dp[0][i][1] = Integer.MIN_VALUE;
        }
        for(int i = 0; i < len+1; i++){
            dp[i][0][0] = 0;
            dp[i][0][1] = Integer.MIN_VALUE;
        }

        for(int i = 1; i < len+1; i++){
            dp[i][1][0] = Math.max(dp[i-1][1][0], dp[i-1][1][1]+prices[i-1]);
            dp[i][1][1] = Math.max(dp[i-1][1][1], dp[i-1][0][0]-prices[i-1]);
            dp[i][2][0] = Math.max(dp[i-1][2][0], dp[i-1][2][1]+prices[i-1]);
            dp[i][2][1] = Math.max(dp[i-1][2][1], dp[i-1][1][0]-prices[i-1]);
        }
        return dp[len][2][0];
    }
}

(9)188. 买卖股票的最佳时机 IV

class Solution {
    public int maxProfit(int k, int[] prices) {
        int len = prices.length;
        int[][][] dp = new int[len+1][k+1][2];

        for(int i = 0; i < k+1; i++){
            dp[0][i][0] = 0;
            dp[0][i][1] = Integer.MIN_VALUE;
        }
        for(int i = 0; i < len+1; i++){
            dp[i][0][0] = 0;
            dp[i][0][1] = Integer.MIN_VALUE;
        }

        for(int i = 1; i < len+1; i++){
            for(int j = 1; j < k+1; j++){
                dp[i][j][0] = Math.max(dp[i-1][j][0], dp[i-1][j][1]+prices[i-1]);
                dp[i][j][1] = Math.max(dp[i-1][j][1], dp[i-1][j-1][0]-prices[i-1]);
            }
        }
        return dp[len][k][0];
    }
}

(10)309. 最佳买卖股票时机含冷冻期

画出状态转移图,注意初始值的设置

class Solution {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        if(len < 2){
            return 0;
        }
        int[][] dp = new int[len+1][3];
        for(int i = 0; i < 3; i++){
            dp[0][1] = Integer.MIN_VALUE;
            dp[0][2] = Integer.MIN_VALUE;
        }
        for(int i = 1; i < len+1; i++){
            dp[i][0] = Math.max(dp[i-1][0], dp[i-1][2]);
            dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0]-prices[i-1]);
            dp[i][2] = dp[i-1][1]+prices[i-1];
        }
        return Math.max(dp[len][0],dp[len][2]);
    }
}

(11)714. 买卖股票的最佳时机含手续费

class Solution {
    public int maxProfit(int[] prices, int fee) {
        int len = prices.length;
        if(len < 2){
            return 0;
        }
        int[][] dp = new int[len+1][2];
        dp[0][0] = 0;
        dp[0][1] = Integer.MIN_VALUE;
        for(int i = 1; i < len+1; i++){
            dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1]+prices[i-1]);
            dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0]-prices[i-1]-fee);
        }
        return dp[len][0];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值