Contents

Binary Search

The size of search spaces ([l, m] or [m, l]) is reduced roughly by a half of the previous iteration, and will eventually reduced to 2 elements and then 1 element at last.

Priciples of Binary Search

  • we must guarantee the search space will decrease over timr (after each iteration).
  • we must guarantee the target will not be ruled out when the value of left or right index changes. (it is critical to define how to move the range for searching)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18

public int binarySearch(int[] arr) {
	int left = 0;
	int right = arr.length - 1;

	while (left <= right) {	// why there include =, if arr size is 1, like target = 4, arr {4}....
		int mid = left + (right - left) / 2; 
		if (arr[mid] == target) {
			return mid;
		} else if (arr[mid] < target) {
			left = mid + 1; // left = mid; wrong! the dead loop will happen when search space <= 2
		} lese {
			right = mid - 1;
		}
	}

	return -1;
}

Time Complexity: O(log_2(n))

… in 2D Space

 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

public boolean isFind(int[][] matrix, int target) {
	if (matrix.length == 0 || matrix[0].length == 0) {
		return false;
	}

	int r = matrix.length;
	int c = matrix[0].length;
	int left = 0;
	int right = r * c - 1;

	while (left <= right) {
		int mid = left + (right - left) / 2;
		int row = mid / r;
		int col = mid % c;
		if (matrix[row][col] == target) {
			return true;
		} else if (matrix[row[row][col] < target) {
			left = mid + 1;
		} else {
			right = mid - 1;
		}

		return false;
	}
}

Time Complexity: O(log_2(m*n))

Closest Element to Target

when you only have 2 elements in the search space, then you only need to check whether the left or right is the answer.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22

public int binarySearch(int[] arr, int target) {
	int left = 0;
	int right = arr.length - 1;

	while (left < right - 1) { // when left neighbors right, we terminate the loop
		int mid = left + (right - left) / 2;
		if (arr[mid] == target) {
			return mid;
		} else if (arr[mid] < target) {
			left = mid;
		} else {
			right = mid;
		}
	}

	if (Math.abs(arr[left] - target) < Math.abs(arr[right] - target)) {
		return left;
	} else {
		return right;
	}
}

First Target

return the first occurrence of the index.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

public int binarySearch(int[] arr, int target) {
	int left = 0;
	int right = arr.length - 1;

	while (right < left - 1) {
		int mid = left + (right - left) / 2;
		if (arr[mid] >= target) {
			right = mid;
		} else {
			left = mid;
		}
	}

	if (arr[left] == target) {
		return left;
	} else if (arr[right] == target) {
		return right;
	} else {
		return -1;
	}

}

Last Target

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

public int binarySearch(int[] arr, int target) {
	int left = 0;
	int right = arr.length - 1;

	while (right < left - 1) {
		int mid = left + (right - left) / 2;
		if (arr[mid] <= target) {
			left = mid;
		} else {
			right = mid;
		}
	}

	if (arr[right] == target) {
		return right;
	} else if (arr[left] == target) {
		return left;
	} else {
		return -1;
	}

}

Closest K Elements

 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
47
48
49
50

public class Solution {
  public int[] kClosest(int[] array, int target, int k) {
    // Write your solution here    
    int left = 0;
    int right = array.length - 1;
    int[] ans = new int[k];
    int i = 0;

    if (array.length == 1) {
      if (k == 1) {
        ans[i] = array[0];
      }
      return ans;
    }

    while (left < right - 1) {
      int mid = left + (right - left) / 2;
      if (array[mid] == target) {
        ans[i++] = array[mid];
        left = mid - 1;
        right = mid + 1;
        break;
      } else if (array[mid] < target) {
        left = mid;
      } else {
        right = mid;
      }
    }

    for (; i < k; i++) {
      if (right >= array.length) {
        ans[i] = array[left--];
        continue;
      }
      if (left < 0) {
        ans[i] = array[right++];
        continue;
      }
      if (Math.abs(array[left] - target) <= Math.abs(array[right] - target)) {
        ans[i] = array[left--];
      } else {
        ans[i] = array[right++];
      }
    }

    return ans;
  }
}

Smallest element that is Larger than the target

 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

public class Solution {
  public int smallestElementLargerThanTarget(int[] array, int target) {
    // Write your solution here
    int left = 0;
    int right = array.length - 1;
    int i = 0;

    if (array == null || array.length == 0) {
      return -1;
    } else if (array.length == 1) {
      if (array[0] > target) {
        return 0;
      }
      return -1;
    }

    while (left < right - 1) {
      int mid = left + (right - left) / 2;
      if (array[mid] <= target) {
        left = mid;
      } else {
        right = mid;
      }
    }

    while (left < array.length) {
      if (array[left] <= target) {
        left ++;
      } else {
        return left;
      }
    }

    return -1;
  }
}