总结

1
2
3
4
5
6
7
8
// 1. 计算数组的和
int[] nums;
int total = Arrays.stream(nums).sum();

// 2. 排序
int[] nums;
Arrays.sort(nums1);

轮转数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public void rotate(int[] nums, int k) {
k = k%nums.length;
swap(nums,0,nums.length-1);
swap(nums,0,k-1);
swap(nums,k,nums.length-1);
}

private void swap(int[] nums,int begin,int end) {
while (begin < end) {
int temp = nums[begin];
nums[begin] = nums[end];
nums[end] = temp;
begin ++; end --;
}
}
}

加一

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public int[] plusOne(int[] digits) {
for (int i = digits.length - 1; i >= 0; i--) {
digits[i]++;
digits[i] = digits[i] % 10;
if (digits[i] != 0) return digits;
}
// 只有类似 9 99 999 这类数才会走到这里
digits = new int[digits.length + 1];
digits[0] = 1;
return digits;
}
}

寻找数组的中心下标

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int pivotIndex(int[] nums) {
int total = Arrays.stream(nums).sum();

int sum = 0;
for (int i = 0; i< nums.length; i++) {
if (2*sum + nums[i] == total) {
return i;
}
sum += nums[i];
}
return -1;

}
}

最长连续1的个数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public int findMaxConsecutiveOnes(int[] nums) {
int maxCount = 0, count = 0;
int n = nums.length;
for (int i = 0; i < n; i++) {
if (nums[i] == 1) {
count++;
} else {
maxCount = Math.max(maxCount, count);
count = 0;
}
}
maxCount = Math.max(maxCount, count);
return maxCount;
}
}

除自身以外数组的乘积

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

class Solution {
public int[] productExceptSelf(int[] nums) {
int length = nums.length;

// L 和 R 分别表示左右两侧的乘积列表
int[] L = new int[length];
int[] R = new int[length];

int[] answer = new int[length];

// L[i] 为索引 i 左侧所有元素的乘积
// 对于索引为 '0' 的元素,因为左侧没有元素,所以 L[0] = 1
L[0] = 1;
for (int i = 1; i < length; i++) {
L[i] = nums[i - 1] * L[i - 1];
}

// R[i] 为索引 i 右侧所有元素的乘积
// 对于索引为 'length-1' 的元素,因为右侧没有元素,所以 R[length-1] = 1
R[length - 1] = 1;
for (int i = length - 2; i >= 0; i--) {
R[i] = nums[i + 1] * R[i + 1];
}

// 对于索引 i,除 nums[i] 之外其余各元素的乘积就是左侧所有元素的乘积乘以右侧所有元素的乘积
for (int i = 0; i < length; i++) {
answer[i] = L[i] * R[i];
}

return answer;
}
}

二分查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public int search(int[] nums, int target) {
int left = 0,right = nums.length - 1;
while(left<=right) {
int mid = (right-left)/2 + left;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] > target) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return -1;
}
}

x 的平方根

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
// 二分查找法
public int mySqrt(int x) {
int l = 0, r = x, ans = -1;
while (l <= r) {
int mid = l + (r - l) / 2;
if ((long) mid * mid <= x) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
return ans;
}
}

两个数组的交集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> set1 = new HashSet<Integer>();
Set<Integer> set2 = new HashSet<Integer>();
for (int num : nums1) {
set1.add(num);
}
for (int num : nums2) {
set2.add(num);
}
return getIntersection(set1, set2);
}

public int[] getIntersection(Set<Integer> set1, Set<Integer> set2) {
if (set1.size() > set2.size()) {
return getIntersection(set2, set1);
}
Set<Integer> intersectionSet = new HashSet<Integer>();
for (int num : set1) {
if (set2.contains(num)) {
intersectionSet.add(num);
}
}
int[] intersection = new int[intersectionSet.size()];
int index = 0;
for (int num : intersectionSet) {
intersection[index++] = num;
}
return intersection;
}
}

两个数组的交集 II

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
if (nums1.length > nums2.length) {
return intersect(nums2, nums1);
}
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int num : nums1) {
int count = map.getOrDefault(num, 0) + 1;
map.put(num, count);
}
int[] intersection = new int[nums1.length];
int index = 0;
for (int num : nums2) {
int count = map.getOrDefault(num, 0);
if (count > 0) {
intersection[index++] = num;
count--;
if (count > 0) {
map.put(num, count);
} else {
map.remove(num);
}
}
}
return Arrays.copyOfRange(intersection, 0, index);
}
}

寻找重复数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public int findDuplicate(int[] nums) {
int n = nums.length;
int l = 1, r = n - 1, ans = -1;
while (l <= r) {
int mid = (l + r) >> 1;
int cnt = 0;
for (int i = 0; i < n; ++i) {
if (nums[i] <= mid) {
cnt++;
}
}
if (cnt <= mid) {
l = mid + 1;
} else {
r = mid - 1;
ans = mid;
}
}
return ans;
}
}

长度最小的子数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 二分查找算法
class Solution {
public int minSubArrayLen(int s, int[] nums) {
int n = nums.length;
if (n == 0) {
return 0;
}
int ans = Integer.MAX_VALUE;
int[] sums = new int[n + 1];
// 为了方便计算,令 size = n + 1
// sums[0] = 0 意味着前 0 个元素的前缀和为 0
// sums[1] = A[0] 前 1 个元素的前缀和为 A[0]
// 以此类推
for (int i = 1; i <= n; i++) {
sums[i] = sums[i - 1] + nums[i - 1];
}
for (int i = 1; i <= n; i++) {
int target = s + sums[i - 1];
int bound = Arrays.binarySearch(sums, target);
if (bound < 0) {
bound = -bound - 1;
}
if (bound <= n) {
ans = Math.min(ans, bound - (i - 1));
}
}
return ans == Integer.MAX_VALUE ? 0 : ans;
}
}

两数之和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 二分查找
class Solution {
public int[] twoSum(int[] numbers, int target) {
for (int i = 0; i < numbers.length; ++i) {
int low = i + 1, high = numbers.length - 1;
while (low <= high) {
int mid = (high - low) / 2 + low;
if (numbers[mid] == target - numbers[i]) {
return new int[]{i + 1, mid + 1};
} else if (numbers[mid] > target - numbers[i]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
}
return new int[]{-1, -1};
}
}

// 双指针
class Solution {
public int[] twoSum(int[] numbers, int target) {
int low = 0, high = numbers.length - 1;
while (low < high) {
int sum = numbers[low] + numbers[high];
if (sum == target) {
return new int[]{low + 1, high + 1};
} else if (sum < target) {
++low;
} else {
--high;
}
}
return new int[]{-1, -1};
}
}

反转字符串

1
2
3
4
5
6
7
8
9
10
11
class Solution {
public void reverseString(char[] s) {
int n = s.length;
for (int left = 0, right = n - 1; left < right; ++left, --right) {
// 交换两个字符
char tmp = s[left];
s[left] = s[right];
s[right] = tmp;
}
}
}

反转字符串中的元音字母

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Solution {
public String reverseVowels(String s) {
int n = s.length();
char[] arr = s.toCharArray();
int i = 0, j = n - 1;
while (i < j) {
while (i < n && !isVowel(arr[i])) {
++i;
}
while (j > 0 && !isVowel(arr[j])) {
--j;
}
if (i < j) {
swap(arr, i, j);
++i;
--j;
}
}
return new String(arr);
}

// 判断是否是元音字符
public boolean isVowel(char ch) {
return "aeiouAEIOU".indexOf(ch) >= 0;
}

// 交换字符数组arr的i和j位子的元素
public void swap(char[] arr, int i, int j) {
char temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}

有效三角形的个数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 排序+双指针
class Solution {
public int triangleNumber(int[] nums) {
int n = nums.length;
Arrays.sort(nums);
int ans = 0;
for (int i = 0; i < n; ++i) {
int k = i;
for (int j = i + 1; j < n; ++j) {
while (k + 1 < n && nums[k + 1] < nums[i] + nums[j]) {
++k;
}
ans += Math.max(k - j, 0);
}
}
return ans;
}
}

删除有序数组中的重复项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public int removeDuplicates(int[] nums) {
int n = nums.length;
if (n == 0) {
return 0;
}
// 快慢指针
int fast = 1, slow = 1;
while (fast < n) {
if (nums[fast] != nums[fast - 1]) {
nums[slow] = nums[fast];
++slow;
}
++fast;
}
return slow;
}
}

两个数组的交集 II

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
// 排序 + 分离双指针
Arrays.sort(nums1);
Arrays.sort(nums2);
int length1 = nums1.length, length2 = nums2.length;
int[] intersection = new int[Math.min(length1, length2)];
int index1 = 0, index2 = 0, index = 0;
while (index1 < length1 && index2 < length2) {
if (nums1[index1] < nums2[index2]) {
index1++;
} else if (nums1[index1] > nums2[index2]) {
index2++;
} else {
intersection[index] = nums1[index1];
index1++;
index2++;
index++;
}
}
return Arrays.copyOfRange(intersection, 0, index);
}
}

长度为 K 的无重复字符子串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 固定长度窗口题目
public int numKLenSubstrNoRepeats(String s, int k) {
int len = s.length();
if (k > 26 || k > len) // 如果 K 大于 26 或字符串长度,直接返回 0
return 0;
int count = 0;
for (int i = 0; i <= len - k; i++) {
String substring = s.substring(i, i + k); // 提取长度为 K 的子串
Set<Character> charSet = new HashSet<>();
for (char c : substring.toCharArray()) {
charSet.add(c); // 将子串中的字符添加到 HashSet 中
}
if (charSet.size() == k) { // 如果 HashSet 的大小等于 K,说明没有重复字符
count++;
}
}
return count; // 返回满足条件的子串数目
}

长度为 K 的无重复字符子串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public int numKLenSubstrNoRepeats(String s, int k) {
int len = s.length();
if (k > 26 || k > len) // 如果 K 大于 26 或字符串长度,直接返回 0
return 0;
int count = 0;
for (int i = 0; i <= len - k; i++) {
String substring = s.substring(i, i + k); // 提取长度为 K 的子串
Set<Character> charSet = new HashSet<>();
for (char c : substring.toCharArray()) {
charSet.add(c); // 将子串中的字符添加到 HashSet 中
}
if (charSet.size() == k) { // 如果 HashSet 的大小等于 K,说明没有重复字符
count++;
}
}
return count; // 返回满足条件的子串数目
}

最长连续递增序列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 连续递增序列,表示不能中断
class Solution {
// 贪心算法
public int findLengthOfLCIS(int[] nums) {
int ans = 0;
int n = nums.length;
int start = 0;
for (int i = 0; i < n; i++) {
if (i > 0 && nums[i] <= nums[i - 1]) {
start = i;
}
ans = Math.max(ans, i - start + 1);
}
return ans;
}
}

最大连续1的个数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public int findMaxConsecutiveOnes(int[] nums) {
int maxCount = 0, count = 0;
int n = nums.length;
for (int i = 0; i < n; i++) {
if (nums[i] == 1) {
count++;
} else {
maxCount = Math.max(maxCount, count);
count = 0;
}
}
maxCount = Math.max(maxCount, count);
return maxCount;
}
}

最大连续1的个数 III

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
public int longestOnes(int[] nums, int k) {
int n = nums.length;
int[] P = new int[n + 1];
for (int i = 1; i <= n; ++i) {
P[i] = P[i - 1] + (1 - nums[i - 1]);
}

int ans = 0;
for (int right = 0; right < n; ++right) {
int left = binarySearch(P, P[right + 1] - k);
ans = Math.max(ans, right - left + 1);
}
return ans;
}

public int binarySearch(int[] P, int target) {
int low = 0, high = P.length - 1;
while (low < high) {
int mid = (high - low) / 2 + low;
if (P[mid] < target) {
low = mid + 1;
} else {
high = mid;
}
}
return low;
}
}

最小覆盖子串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class Solution {
Map<Character, Integer> ori = new HashMap<Character, Integer>();
Map<Character, Integer> cnt = new HashMap<Character, Integer>();

public String minWindow(String s, String t) {
int tLen = t.length();
for (int i = 0; i < tLen; i++) {
char c = t.charAt(i);
ori.put(c, ori.getOrDefault(c, 0) + 1);
}
int l = 0, r = -1;
int len = Integer.MAX_VALUE, ansL = -1, ansR = -1;
int sLen = s.length();
while (r < sLen) {
++r;
if (r < sLen && ori.containsKey(s.charAt(r))) {
cnt.put(s.charAt(r), cnt.getOrDefault(s.charAt(r), 0) + 1);
}
while (check() && l <= r) {
if (r - l + 1 < len) {
len = r - l + 1;
ansL = l;
ansR = l + len;
}
if (ori.containsKey(s.charAt(l))) {
cnt.put(s.charAt(l), cnt.getOrDefault(s.charAt(l), 0) - 1);
}
++l;
}
}
return ansL == -1 ? "" : s.substring(ansL, ansR);
}

public boolean check() {
Iterator iter = ori.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
Character key = (Character) entry.getKey();
Integer val = (Integer) entry.getValue();
if (cnt.getOrDefault(key, 0) < val) {
return false;
}
}
return true;
}
}

将 x 减到 0 的最小操作数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
public int minOperations(int[] nums, int x) {
int n = nums.length;
int sum = Arrays.stream(nums).sum();

if (sum < x) {
return -1;
}

int right = 0;
int lsum = 0, rsum = sum;
int ans = n + 1;

for (int left = -1; left < n; ++left) {
if (left != -1) {
lsum += nums[left];
}
while (right < n && lsum + rsum > x) {
rsum -= nums[right];
++right;
}
if (lsum + rsum == x) {
ans = Math.min(ans, (left + 1) + (n - right));
}
}

return ans > n ? -1 : ans;
}
}

替换后的最长重复字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public int characterReplacement(String s, int k) {
// 区间中,每个大写字符出现的次数;
int[] num = new int[26];
int n = s.length();
// 区间中,字符最多的出现次数
int maxn = 0;
int left = 0, right = 0;
while (right < n) {
num[s.charAt(right) - 'A']++;
maxn = Math.max(maxn, num[s.charAt(right) - 'A']);
if (right - left + 1 - maxn > k) {
num[s.charAt(left) - 'A']--;
left++;
}
// 区间中没有满足题意的解
right++;
}
return right - left;
}
}

验证回文串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
// 双指针
public boolean isPalindrome(String s) {
int n = s.length();
int left = 0, right = n - 1;
while (left < right) {
while (left < right && !Character.isLetterOrDigit(s.charAt(left))) {
++left;
}
while (left < right && !Character.isLetterOrDigit(s.charAt(right))) {
--right;
}
if (left < right) {
if (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))) {
return false;
}
++left;
--right;
}
}
return true;
}
}

最长回文子串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public String longestPalindrome(String s) {
if (s == null || s.length() < 1) {
return "";
}
int start = 0, end = 0;
for (int i = 0; i < s.length(); i++) {
int len1 = expandAroundCenter(s, i, i);
int len2 = expandAroundCenter(s, i, i + 1);
int len = Math.max(len1, len2);
if (len > end - start) {
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}

public int expandAroundCenter(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
--left;
++right;
}
return right - left - 1;
}
}

无重复字符的最长子串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public int lengthOfLongestSubstring(String s) {
// 哈希集合,记录每个字符是否出现过
Set<Character> occ = new HashSet<Character>();
int n = s.length();
// 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
int rk = -1, ans = 0;
for (int i = 0; i < n; ++i) {
if (i != 0) {
// 左指针向右移动一格,移除一个字符
occ.remove(s.charAt(i - 1));
}
while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) {
// 不断地移动右指针
occ.add(s.charAt(rk + 1));
++rk;
}
// 第 i 到 rk 个字符是一个极长的无重复字符子串
ans = Math.max(ans, rk - i + 1);
}
return ans;
}
}

大小为 K 且平均值大于等于阈值的子数组数目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public int numOfSubarrays(int[] arr, int k, int threshold) {
int length = arr.length;
if (length < k) {
return 0;
}
int res = 0;
for (int i = 0; i <= length - k; i++) {
int sum = 0;
for (int j = i; j < k + i; j++) {
sum = sum + arr[j];
}
int avg = sum/k;
if (avg >= threshold) {
res ++;
}
}
return res;
}
}

子数组最大平均数 I

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public double findMaxAverage(int[] nums, int k) {
int sum = 0;
int n = nums.length;
for (int i = 0; i < k; i++) {
sum += nums[i];
}
int maxSum = sum;
for (int i = k; i < n; i++) {
sum = sum - nums[i - k] + nums[i];
maxSum = Math.max(maxSum, sum);
}
return 1.0 * maxSum / k;
}
}

子集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
List<Integer> t = new ArrayList<Integer>();
List<List<Integer>> ans = new ArrayList<List<Integer>>();

public List<List<Integer>> subsets(int[] nums) {
int n = nums.length;
for (int mask = 0; mask < (1 << n); ++mask) {
t.clear();
for (int i = 0; i < n; ++i) {
if ((mask & (1 << i)) != 0) {
t.add(nums[i]);
}
}
ans.add(new ArrayList<Integer>(t));
}
return ans;
}
}

子集 II

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
List<Integer> t = new ArrayList<Integer>();
List<List<Integer>> ans = new ArrayList<List<Integer>>();

public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(nums);
int n = nums.length;
for (int mask = 0; mask < (1 << n); ++mask) {
t.clear();
boolean flag = true;
for (int i = 0; i < n; ++i) {
if ((mask & (1 << i)) != 0) {
// 没有选择上一个数,且当前数字与上一个数相同
if (i > 0 && (mask >> (i - 1) & 1) == 0 && nums[i] == nums[i - 1]) {
flag = false;
break;
}
t.add(nums[i]);
}
}
if (flag) {
ans.add(new ArrayList<Integer>(t));
}
}
return ans;
}
}



本站由 卡卡龙 使用 Stellar 1.29.1主题创建

本站访问量 次. 本文阅读量 次.