数组/字符串
第一题: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;
}
}