Long Luo's Life Notes

每一天都是奇迹

By Long Luo

这篇文章是 287. 寻找重复数 的题解。

目前这道题,经过自己摸索和参考 官方题解: 寻找重复数 ,目前发现了9种方法。

这些方法可以分为以下几类:

  • 需要额外空间,需要修改原始数组 \(O(logn)\) space
    • 排序 - \(O(nlogn)\) time
  • 需要额外空间,不修改原始数组 \(O(n)\) space
    • 计数法 - \(O(n)\) time
    • Set - \(O(n)\) time
  • 不需要额外空间,需要修改原始数组 \(O(1)\) space
    • 标记法 - \(O(n)\) time
    • 索引排序 - \(O(n)\) time
  • 不需要额外空间,不修改原始数组 \(O(1)\) space
    • 暴力 - \(O(n^2)\) time
    • 二分搜索 - \(O(nlogn)\) time
    • 位运算 - O(nlogn) time
    • 双指针 - \(O(n)\) time

因为题目要求:

  1. 必须不修改数组 \(\textit{nums}\)
  2. 只用常量级 \(O(1)\) 的额外空间。

因此我们先从需要修改数组的方案开始,下面我们就来一一分析:

需要额外空间,需要修改原始数组

方法一:排序

先对数组进行排序,然后遍历数组,如果出现重复数字既是答案。

1
2
3
4
5
6
7
8
9
10
11
12
// Sort
public static int findDuplicate_sort(int[] nums) {
Arrays.sort(nums);
int len = nums.length;
for (int i = 1; i < len; i++) {
if (nums[i] == nums[i - 1]) {
return nums[i];
}
}

return len;
}

复杂度分析

  • 时间复杂度:\(O(nlogn + n)\),其中 \(n\)\(\textit{nums}\) 数组的长度,\(O(logn)\) 排序复杂度,总时间复杂度为 \(O(nlogn + n)\)
  • 空间复杂度:\(O(logn)\),排序需要使用 \(O(logn)\) 空间。

需要额外空间,不修改原始数组

方法二:计数法

因为数组元素值的范围是 \([1, n]\) 之间,那么可以使用一个数组来记录数字出现次数,次数大于 \(1\) 即为答案。

1
2
3
4
5
6
7
8
9
10
11
12
13
// Count
public static int findDuplicate_count(int[] nums) {
int len = nums.length;
int[] cnt = new int[len + 1];
for (int i = 0; i < len; i++) {
cnt[nums[i]]++;
if (cnt[nums[i]] > 1) {
return nums[i];
}
}

return len;
}

复杂度分析

  • 时间复杂度:\(O(n)\),其中 \(n\)\(\textit{nums}\) 数组的长度。
  • 空间复杂度:\(O(n)\),需要新建一个长度为 \(n\) 的数组。

方法三:HashSet

同方法二,这里使用HashSet来记录数组元素。

1
2
3
4
5
6
7
8
9
10
11
12
// Set
public static int findDuplicate_set(int[] nums) {
Set<Integer> set = new HashSet<>();
int len = nums.length;
for (int i = 0; i < len; i++) {
if (!set.add(nums[i])) {
return nums[i];
}
}

return len;
}

复杂度分析

  • 时间复杂度:\(O(n)\),其中 \(n\)\(\textit{nums}\) 数组的长度。
  • 空间复杂度:\(O(n)\)
阅读全文 »

By Long Luo

This article is the solution of Problem 81. Search in Rotated Sorted Array II.

Brute Force

The Brute Force solution is so easy.

Problem 33. Search in Rotated Sorted Array.

1
2
3
4
5
6
7
8
9
10
public static int search_bf(int[] nums, int target) {
int len = nums.length;
for (int i = 0; i < len; i++) {
if (nums[i] == target) {
return i;
}
}

return -1;
}

Problem 81. Search in Rotated Sorted Array II:

1
2
3
4
5
6
7
8
9
10
public static boolean search_bf(int[] nums, int target) {
int len = nums.length;
for (int i = 0; i < len; i++) {
if (nums[i] == target) {
return true;
}
}

return false;
}

Analysis

  • Time Complexity: \(O(n)\).
  • Space Complexity: \(O(1)\).

Binary Search

Step-by-step Binary Search Algorithm:

We basically ignore half of the elements just after one comparison.

  1. Compare target with the middle element;
  2. If target matches with the middle element, we return the mid index;
  3. Else If target is greater than the mid element, then target can only lie in the right half subarray after the mid element. So we recursive for the right half;
  4. Else (target is smaller) recursive for the left half.

The Key of Binary Search is Narrow the Search Interval, aka reducing the scale of the problem.

Every round exclusive the interval where the target element must not exist, so the scale of the problem is gradually reduced.

Problem 33. Search in Rotated Sorted Array.

阅读全文 »

By Long Luo

This article is the solution Greedy: Sorting the Costs Array by What? of Problem 1029. Two City Scheduling.

Intuition

Let’s use it by Brute Force way.

The array \(\textit{costs}\) length is \(n\), so all the total choices will be \(2^n\), that’s a really huge number, so we must find a better way!

Greedy

Obiviously, it’s solved by greedy.

We need to sort the array \(\textit{costs}\) first.

But how to sort it?

By what?

If we choose a person who has lower \(cost_A\), but if his \(cost_B\) is more lower than another person’s \(cost_B\), that means the total cost will be larger.

If let \(2 \times n\) people all fly to city B, then choose \(n\) people of them change to fly city A, the company need a extra cost \(cost_A - cost_B\).

Ahha, Eureka! We Got It!

Sort the array by \(cost_A - cost_B\), the fist \(n\) person to city A, others go to city B.

Let’s coding.

阅读全文 »

By Long Luo

This article is the solution Greedy: Let the Heaviest Match the Lightest, if Not Matched, Let it Alone of Problem 881. boats to save people.

Intuition

We should let the Heaviest person match the Lightest person and create the most pairs whose weight didn’t exceed the limit, and so on.

If not, let the Heavy person occupy a whole boat.

I write the Brute Force code first.

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
public int numRescueBoats(int[] people, int limit) {
int len = people.length;
Arrays.sort(people);
int ans = 0;
int idx = 0;
int right = len - 1;
while (idx < len) {
while (idx < len && people[idx] == 0) {
idx++;
}

while (right > idx && people[right] > 0 && people[idx] + people[right] > limit) {
right--;
}

if (right > idx && people[idx] + people[right] <= limit) {
people[idx] = 0;
people[right] = 0;
idx++;
right--;
ans++;
} else if (idx < len) {
people[idx] = 0;
idx++;
ans++;
}
}

return ans;
}

It was ugly, then I wrote such code below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 public int numRescueBoats(int[] people, int limit) {
int len = people.length;
Arrays.sort(people);
int left = 0;
int right = len - 1;
int ans = 0;
while (left <= right) {
if (people[left] + people[right] <= limit) {
left++;
right--;
ans++;
} else {
right--;
ans++;
}
}

return ans;
}

Analysis

  • Time Complexity: \(O(nlogn)\)
  • Space Complexity: \(O(logn)\)

All suggestions are welcome. If you have any query or suggestion please comment below. Please upvote👍 if you like💗 it. Thank you:-)

Explore More Leetcode Solutions. 😉😃💗

By Long Luo

This article is the solution Greedy: Reverse Thinking with Binary Algorithm of Problem 991. Broken Calculator.

Intuition

  1. If \(\textit{startValue} \gt \textit{target}\), so return \(\textit{startValue} \gt \textit{target}\);
  2. Considering such cases: \(2 \to 3\), \(2 \to 5\), \(1 \to 128\), \(1 \to 100\);
  3. \(\textit{startValue} = \textit{startValue} \times 2^i\), when \(\textit{startValue}\) grows bigger, the last \(\textit{startValue}\) is closer to \(\textit{target} / 2\) that we only need double \(\textit{startValue}\) once.

So think reversly:

  1. if target is even, the minimum operand is convert \(startValue\) equal to \(\textit{target} / 2 + 1\);
  2. if target is odd, the minimum operand is convert \(startValue\) equal to \((\textit{target} + 1) / 2 + 2\).

Let’s coding.

阅读全文 »
0%