java刷题笔记: 刷通尊享面试100题(1):思路与java知识整理

数组/字符串

在这里插入图片描述

第一题:624. 数组列表中的最大距离

在这里插入图片描述

class Solution {
    public int maxDistance(List<List<Integer>> arrays) {
        int m = arrays.size();
        int[] value = new int[2];
        value[0] = 10000; value[1] = -10000;
        int res = 0;
        for (int i = 0; i < m; i++ ) {
            List<Integer> temp = arrays.get(i);
            int ll = temp.size();
            int a = temp.get(0), b = temp.get(0);
            for (int j = 1; j < ll; j++) {
                a = Math.min (a, temp.get(j));
                b = Math.max (b, temp.get(j));
            }
            res = Math.max(res, value[1] - a);
            res = Math.max(res, b - value[0]);
            value[0] = Math.min(value[0], a);
            value[1] = Math.max(value[1], b);
        }
        return res;
    }
}

第二题: 280. 摆动排序

在这里插入图片描述

第三题:1056. 易混淆数

在这里插入图片描述
简单的模拟即可。

第四题:1427. 字符串的左右移

在这里插入图片描述
简单题复习语法, 复习一下字符串的substring方法。

class Solution {
    public String stringShift(String s, int[][] shift) {
        // 计算最终左移的次数, 左移-1相当于左移n-1
        int xx = 0;
        for (int[] sh:shift) {
            xx += sh[0]==0?sh[1]:-sh[1];
        }
        while (xx <= 0) xx+=s.length();
        xx%=s.length();
        return s.substring(xx) + s.substring(0,xx);
    }
}

第五题:161. 相隔为 1 的编辑距离

在这里插入图片描述
这道太简单了,直接复习下题:
在这里插入图片描述

class Solution {
    public int minDistance(String word1, String word2) {
        int m = word1.length(), n = word2.length();
        char[] ww1 = word1.toCharArray(), ww2 = word2.toCharArray();
        int[][] dp = new int[m+1][n+1];
        for (int j = 0; j < n; j++) {
            dp[0][j+1] = j+1;
        }
        for (int i = 1; i <= m; i++) {
            Arrays.fill(dp[i], m+n);
            dp[i][0] = i;
            for (int j = 1; j <= n; j++) {
                if (ww1[i-1] == ww2[j-1]) {
                    dp[i][j] = dp[i-1][j-1];
                } else {
                    dp[i][j] = 1+dp[i-1][j-1];
                }
                dp[i][j] = Math.min(dp[i][j], 1+dp[i-1][j]);
                dp[i][j] = Math.min(dp[i][j], 1+dp[i][j-1]);
            }
        }
        return dp[m][n];
    }
}

直接把计数部分的代码切换过去也可以直接过但耗时感人。

关于上述的编辑距离,可以直接计算前缀和后缀相等的数量,判断和+1是否等于较大的长度即可。

第六题:186. 反转字符串中的单词 II

在这里插入图片描述
直接反转全部随后反转首尾即可。

class Solution {
    public void reverseWords(char[] s) {
        int n = s.length;
        swapSeries(s, 0, n-1);
        int pre = 0;
        for (int i = 0; i < n; i ++) {
            if (s[i] == ' ') {
                swapSeries(s, pre, i-1);
                pre = i+1;
            }
        }
        swapSeries(s, pre, n-1);
    }
    void swapSeries(char[] s, int from, int end) {
        for (int i = 0; from+i<end-i;i++) {
            swap(s, from+i, end-i);
        }
    }
    void swap(char[] s, int i, int j) {
        s[i] ^= s[j];
        s[j] ^= s[i];
        s[i] ^= s[j];
    }
}

第七题:1055. 形成字符串的最短路径

在这里插入图片描述
观察一下用贪心就行。

class Solution {
    public int shortestWay(String source, String target) {
        int m = source.length(), n = target.length();
        char[] ss = source.toCharArray(), tt = target.toCharArray();
        int ss_len = 0;
        for (int i = 0; i < n; i++ ) {
            boolean match = false;
            for (int j = 0; j < m; j++ ) {
                int s_index = (ss_len+j)%m;
                if (ss[s_index] == tt[i]) {
                    ss_len += j+1;
                    match = true;
                    break;
                }
            }
            if (!match) return -1;
        }
        return (ss_len+m-1)/m;
    }
}

滑动窗口

在这里插入图片描述

第一/二题: 至多包含两/k个不同字符的最长子串

在这里插入图片描述

首先是使用hash表的常规解法

class Solution {
    public int lengthOfLongestSubstringKDistinct(String s, int k) {
        char[] ss = s.toCharArray();
        int n = s.length();
        int[] dp = new int[256];
        int count = 0, res = 0;
        for (int i = 0, j = 0; i < n; i++) {
            if (dp[ss[i]] == 0) {
                count++;
            }
            dp[ss[i]]++;
            while (count > k) {
                dp[ss[j]] --;
                if (dp[ss[j]] == 0) {
                    count--;
                }
                j++;
            }
            // System.out.println("i = " + i + ", j = " + j);
            res = Math.max(res, i-j+1);
        }
        return res;
    }
}

然后想到了一种存下标的做法,但没想到怎么实现。
在这里插入图片描述
根据后续

第三题: 487. 最大连续1的个数 II

在这里插入图片描述

class Solution {
    public int findMaxConsecutiveOnes(int[] nums) {
        int res = 0, n = nums.length;
        int[] count = new int[2];
        for (int i = 0, j = 0; i < n; i++) {
            count[nums[i]]++;
            while (count[0] > 1) {
                count[nums[j]]--;
                j++;
            }
            res = Math.max(res, i-j+1);
        }
        return res;
    }
}
class Solution {
    public int findMaxConsecutiveOnes(int[] nums) {
        int res = 0, n = nums.length;
        int[] dp = new int[2];
        for (int i = 0; i < n; i++) {
            if (nums[i] == 0) {
                dp[1] = dp[0] + 1;
                dp[0] = 0;
            } else {
                dp[0]++; dp[1]++;
            }
            res = Math.max(res, dp[1]);
        }
        return res;
    }
}

第四题: 1100. 长度为 K 的无重复字符子串

在这里插入图片描述
丑陋的代码。

class Solution {
    public int numKLenSubstrNoRepeats(String s, int k) {
        int[] count = new int[257];
        char[] ss = s.toCharArray();
        int n = ss.length, c_num = 0, res = 0;
        for (int i = 0; i < k && i < n; i++) {
            if (++count[ss[i]] == 1) {
                c_num++;
            }
        }
        res += c_num==k ? 1:0;
        for (int i = 1, j = k; j < n; i++, j++ ) {
            if (++count[ss[j]] == 1) c_num++;
            if (--count[ss[i-1]] == 0) c_num--;
            res += c_num==k ? 1:0;
        }
        return res;
    }
}

题解中找到的十分优雅的解法:

class Solution {
    public int numKLenSubstrNoRepeats(String S, int K) {
        int[] last = new int[128];
        Arrays.fill(last, -1);
        int left = -1;
        int ans = 0;
        for (int i = 0; i < S.length(); ++i) {
            left = Math.max(left, last[S.charAt(i)]);
            last[S.charAt(i)] = i;
            if (K <= i - left) {
                ++ans;
            }
        }
        return ans;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ko no 辉夜 da

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值