// Day1 数组理论基础,704. 二分查找,27. 移除元素
// 704. 二分查找
// 一、左閉右「開」寫法 [1,1)
// 1. size=nums.length
// 2. while(left<right)
// 3. right = middle
class Solution{
public int search(int[]nums, int target){
int left = 0;
int right = nums.length; // 沒有右區間,所以不減一
while(left<right){ // 左閉又開,等號 無意義
int middle = left + (right-left)/2;
if (nums[middle]==target){
return middle;
} else if (target<nums[middle]){
right = middle; // 右開,所以可以等於 middle
} else if (target>nums[middle]){
left = middle + 1;
}
}
return -1;
}
}
// 二、左閉右「閉」寫法 [1,1]
// 1. size=nums.length-1
// 2. while(left<=right)
// 3. right = middle-1
class Solution{
public int search(int[]nums, int target){
int left = 0;
int right = nums.length-1; // 有右區間,所以-1
while(left<=right){
int middle = left + (right-left)/2;
if (target == nums[middle]){
return middle;
} else if (target < nums[middle]) {
right = middle -1 ; // 有右區間,所以等於 middle-1
} else if (target > nums[middle]) {
left = middle + 1;
}
}
return -1;
}
}
// 三、遞迴
class Solution {
public int search(int[] nums, int target) {
int result = binarySearch(nums, 0, nums.length-1, target);
return result;
}
private int binarySearch(int[] a, int left, int right, int key){
// If left > right, return -1
if (left>right){
return -1;
}
// Count mid index
int mid = left + (right - left) / 2;
// If key equals to a[mid], return index
if (key == a[mid]){
return mid;
} else if (key<a[mid]) {
// 左側區間搜索
return binarySearch(a, left, mid-1, key);
} else if (key>a[mid]) {
// 右側區間搜索
return binarySearch(a, mid+1, right, key);
}
return -1;
}
}
// 数组中移除元素并不容易! | LeetCode:27. 移除元素
// https://www.bilibili.com/video/BV12A4y1Z7LP/?spm_id_from=333.788
// https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html#%E6%80%9D%E8%B7%AF
// 數組理論基礎
// 1.相同类型元素的一个集合
// 2.在内存中是一段连续的空间
// 3.數組不能刪除、只能覆蓋 [1,2,3,4,5] 刪除3,後面往前覆蓋
// 暴力解法: for迴圈找到之後,後面再用一個for迴圈依次往前覆蓋
class Solution {
public int removeElement(int[] nums, int val) {
int size = nums.length;
for (int i = 0; i < size; i++){
if (nums[i] == val){ // 发现需要移除的元素,就将数组集体向前移动一位
for (int j = i+1; j < size; j++){
nums[j-1] = nums[j];
}
i--; // 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位
size--; // 此时数组的大小-1
}
}
return size;
}
}
// 快慢指針解法:
// 快指針:尋找新數組(刪除目標值)裡面所需要的元素
// 快指針獲取到新數組所需元素後,快指針上獲取的值,賦給慢指針
// 快指針:獲取新數組中的 元素
// 慢指針:獲取新數組中需要 更新的位置
// 在同一數組上操作
// 慢指針:等於0
// 快指針:for 循環,快指針移動
// 更新:
// (1) 快指針所指向的值,不等於要刪除的目標元素 時
// (2) 把值賦給新數組所對應的下標位置(慢指針)
// (3) 慢指針向後移動一格
// 此時,慢指針是新數組,size的大小
class Solution {
public int removeElement(int[] nums, int val){
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.length; fastIndex++){
if (nums[fastIndex] != val){
nums[slowIndex] = nums[fastIndex];
slowIndex++;
}
}
return slowIndex;
}
}