TODO:
27 remove element 解析
[Data Structure] Array
Goal: 了解一下数组基础,以及数组的内存空间地址,数组也没那么简单
704. Binary Search
Binary Search (Data Structure and Algorithm)
- 使用二分法的前提条件:
(a) an array of integers nums which is sorted in ascending order.
(b) All the integers in nums are unique. - 二分法种类(依照边界条件区分):
(a)[left, right]
左闭右闭:while (left <= right)
(b)[left, right)
左闭右开:while (left < right)
### Intuition 题目提到:(1) ascending sorted order, (2) all the integers in nums are unique。由题可知: Binary Search。下一步思考是哪一种 Binary Search? `[left, right]` or `[left, right)`?
Approach 1: [left, right]
左闭右闭
- Time Complexity:
O(log n)
nums
每次被切一半。在 worst-case 情况下,对半切直到该范围没有 element,这将花费O(log n)
- Space Complexity:
O(1)
因为只需要 3 个 index:left
,mid
,right
public int search(int[] nums, int target) {
// edge case
if (target < nums[0] || target > nums[nums.length - 1]) {
return -1;
}
// 如何实作 binary search ?? 找 mid 再移动?
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = (right - left) / 2 + left;
if (nums[mid] == target) {
return mid; // found target value
} else if (nums[mid] > target) { // Q: 搞不清楚怎么换 boundary...需再了解
right = mid - 1; // target 在左区间,在[left, middle - 1] 中
} else {
left = mid + 1; // target 在右区间,在[middle + 1, right] 中
}
}
return -1; // not found target value
}
没有思考到的点:
- edge case 改写:
// avoid (1) target < nums[0] || (2) target > nums[nums.length - 1]
if (target < nums[0] || target > nums[nums.length - 1]) {
return -1;
}
- Why don’t use
int mid = (right + left) / 2;
? it might causeoverflow
Example: int range = 21 亿int left = 21 亿, int right = 22 亿
=>(left + right) / 2 = 21.5 亿 (overflow)
- Solution:
int mid = left + (right - left) /2;
延伸思索
- How to identify
[left, right)
and[left, right]
in the question? - 容易混淆的
while
及左右区间
(1)while (left < right) || while (left <= right)
?
a. 左闭右闭[left, right]
为while (left <= right)
,举例:[1, 1]
合法区间,因为能取到 rigth 值。
b. 左闭右开[left, right)
为while (left < right)
,举例:[1, 1)
不合法区间,所以是<
。
(2)else if (nums[mid] > target) { right = mid - 1 || right = mid }
?
根据区间定义,来给 right 赋值:right = mid - 1 || right = mid
a. 左闭右闭[left, right]
为while (left <= right)
:在此次的搜寻已发现:nums[mid] != target value
,所以下一次搜索要剔除nums[mid]
的
mid
index,所以下一个区间是[left, mid - 1]
b. 左闭右开[left, right)
为while (left < right)
:
if (nums[mid] > target) { // [ target, .., mid] => target 位在左区间
right = mid; // 因为左闭右开,所以 [left, mid) => 直接 right = mid 即可。
} else if ( nums[mid] < target) { // [mid, .., target] => target 位在右区间
left = mid + 1 // 因为在此次搜索中已发现 nums[mid] != target val 所以下一次搜索不包含 nums[mid],要剔除,因此 left = mid + 1。
}
right = nums.length || nums.length - 1
?
a. 左闭右闭[left, right]
为while (left <= right)
:right = nums.length - 1;
b. 左闭右开[left, right)
为while (left < right)
:right = nums.length;
困惑: why 左闭右开[left, right)
为while (left < right)
:right = nums.length;
?
27. Remove Element
Intuition
Approach 1: Brute Force
class Solution {
public int removeElement(int[] nums, int val) {
int size = nums.length;
for (int i = 0 ; i < size ; i++) {
// remove the element which is euqal to val.
if (nums[i] == val) {
for (int j = i + 1 ; j < size ; j++) {
// move all element forward one pos
nums[j-1] = nums[j];
}
}
i--; // i move forward 1 pos because elements behind i move forward 1 pos
size--; // array size - 1 beacuse remove 1 element that value is equal to val.
}
}
}
}
Approach 2: Two-Pointers
class Solution {
public int removeElement(int[] nums, int val) {
int slow = 0;
for (int fast = 0 ; fastIdx < nums.length ; fast++) {
if (nums[fast] != val) {
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
}
Related Questions:
- Binary Search
- Easy - 35. Search Insert Position
- Easy - 34. Find First and Last Position of Element in Sorted Array
- Easy - 69. Sqrt(x)
- Easy - 367. Valid Perfect Square
- Remove element
- Easy - 26. Remove Duplicates from Sorted Array
- Easy - 283. Move Zeroes
- Easy - 844. Backspace String Compare
- Easy - 977. Squares of a Sorted Array