Given a 2D board and a word, find if the word exists in the grid. The word can be constructed from letters of sequentially adjacent cell, where “adjacent” cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once. For example:
Given word = "ABCCED", return true. Given word = "SEE", return true. Given word = "ABCB", return false.
The word search problem is similarly to the number of islands problem. What we need to do is to look through the grid, and once we find the first letter of the word, we need to DFS the surrounding letters.
publicclassWordSearch{ publicbooleanexist(char[][] board, String word){ // Traverse the board for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[i].length; j++) { // Once we find the first letter of the word, we begin DFS. if (board[i][j] == word.charAt(0) && dfs(board, i, j, word, 0)) { returntrue; } } }
returnfalse; }
publicbooleandfs(char[][] board, int i, int j, String word, int index){ if (index == word.length()) { returntrue; }
if (i < 0 || i >= board.length || j < 0 || j >= board[i].length || board[i][j] != word.charAt(index)) { returnfalse; }
// The same letter cell may not be used more than once. // Therefore, we temporally "erase" the current letter. char temp = board[i][j]; board[i][j] = ' '; // Search up, down, right, left boolean result = dfs(board, i - 1, j, word, index + 1) || dfs(board, i + 1, j, word, index + 1) || dfs(board, i, j - 1, word, index + 1) || dfs(board, i, j + 1, word, index + 1); board[i][j] = temp;
return result; } }
The process of the above code is like this:
2. Letter Combinations of a Phone Number
Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent. A mapping of digit to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters.
Given a set of distinct integers, nums, return all possible subsets (the power set). Note: The solution set must not contain duplicate subsets. For example:
publicclassSubsets{ public List<List<Integer>> subsets(int[] nums) { List<List<Integer>> results = new ArrayList<>(); dfs(nums, 0, new ArrayList<Integer>(), results);
return results; }
publicvoiddfs(int[] nums, int index, List<Integer> combination, List<List<Integer>> results){ results.add(new ArrayList<>(combination)); // We cannot write the above code like this: // results.add(combination); // Because every time we are adding the same reference.
for (int i = index; i < nums.length; i++) { combination.add(nums[i]); dfs(nums, i + 1, combination, results); combination.remove(combination.size() - 1); } } }
The process of the above code is like this:
5. Search in Rotated Sorted Array
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]). You are given a target value to search. If found in the array return its index, otherwise return -1.
You may assume no duplicate exists in the array. Your algorithm’s runtime complexity must be in the order of O(log n).
As our algorithm must be in O(log n), we should find the pivot and do the binary search. Firstly we should understand what is binary search, here is the code for standard binary search:
// 1. Using iteration // Suppose the array nums is sorted in ascending order. publicintbinarySearch(int[] nums, int target){ int left = 0; int right = nums.length - 1; while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] > target) { right = mid - 1; } elseif (nums[mid] < target) { left = mid + 1; } else { return mid; } }
return -1; }
// --------------------------------------------------------------- // 2. Using Recursion // Suppose the array nums is sorted in ascending order. publicintbinarySearch(int[] nums, int target){ return binarySearch(nums, target, 0, nums.length - 1); }
publicintbinarySearch(int[] nums, int target, int left, int right){ int mid = left + (right - left) / 2; if (nums[mid] == target) { return target; } elseif (nums[mid] < target) { return binarySearch(nums, target, mid + 1, right); } else { return binarySearch(nums, target, left, mid - 1); } }
For this problem, as we do not know the pivot beforehand, we can firstly find the maximum or minimum number in the array, then we can know where the pivot is. After finding out the pivot, we can use binary search to find the target.
We can find the minimum number in a sorted array like this:
// 1. Using iteration publicintfindMin(int[] nums){ int left = 0; int right = nums.length - 1;
while (left < right) { int mid = left + (right - left) / 2; if (nums[mid] > nums[right]) { left = mid + 1; } else { right = mid; } }
return nums[left]; }
// ------------------------------------------- // 2. Using recursion // Note that this code would cause StackOverflowError in Java. publicintfindMin(int[] nums){ return findMin(nums, 0, nums.length - 1); } publicintfindMin(int[] nums, int left, int right){ if (left + 1 >= right) {// only 1 or 2 elements return Math.min(nums[left], nums[right]); } if (nums[left] < nums[right]) {// sorted return nums[left]; } int mid = left + (left + right) / 2; int leftMin = findMin(nums, left, mid - 1); int rightMin = findMin(nums, mid, right); return Math.min(leftMin, rightMin); }
Now, let’s go back to our original problem, searching a target number in rotated sorted array. Here is the code to solve the problem:
publicclassSearchInRotatedSortedArray{ publicintsearch(int[] nums, int target){ if (nums.length == 0) { return -1; }
// 1. We can firstly find the minimum number of the array, which // tells us where the pivot is. int left = 0; int right = nums.length - 1; while (left < right) { int mid = left + (right - left) / 2; if (nums[mid] > nums[right]) { left = mid + 1; } else { right = mid; } }
// 2. After the while loop, right/left is the index of the minimum number. And // we need to make sure which part we should use to find the target. int pivot = left;// or right left = 0; right = nums.length - 1; if (target >= nums[pivot] && target <= nums[right]) { left = pivot; } else { right = pivot; }
// 3. We do the binary search to find the target. while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target) { return mid; } elseif (nums[mid] > target) { right = mid - 1; } else { left = mid + 1; } }
return -1; }
}
The process of the above code is like this:
6.Number of Islands
Given a 2d grid map of 1s (land) and 0s (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
For example, if we have a grid like this:
1 2 3 4
11110 11010 11000 00000
The number of islands is 1:
If we have a grid like this:
1 2 3 4
11000 11000 00100 00011
The number of islands is 3:
To solve the problem, we need a counter to record the number of islands. At the beginning, the counter is set to 0. What we need to do is to traverse the grid, and once we find a land, we change this land to water(change 1 to 0). Then we search the surrounding lands and also change them to water. After we “merge” all the adjacent lands, we increase our counter and continue to traverse the grid.
int numOfIslands = 0;// a counter to record the number of islands
// traverse the grid for (int i = 0; i < grid.length; i++) { for (int j = 0; j < grid[i].length; j++) { // once we find a land, we search and "merge" all its surrounding lands // and increase the counter by 1 if (grid[i][j] == '1') { dfs(grid, i, j); numOfIslands++; } } }
return numOfIslands; }
// search all surround lands of land(i,j), and change them from 1 to 0 publicstaticvoiddfs(char[][] grid, int i, int j){ if (i < 0 || i >= grid.length || j < 0 || j >= grid[i].length || grid[i][j] == '0') { return; }
grid[i][j] = '0'; dfs(grid, i - 1, j);// search up dfs(grid, i + 1, j);// search down dfs(grid, i, j - 1);// search left dfs(grid, i, j + 1); // search right } // main method to test the numOfIslands method. publicstaticvoidmain(String[] args){ char[][] grid = { {'1', '1', '0', '0', '0'}, {'1', '1', '0', '0', '0'}, {'0', '0', '1', '0', '0'}, {'0', '0', '0', '1', '1'}};