74. Search a 2D Matrix

问题
Write an efficient algorithm that searches for a value target in an m x n integer matrix matrix. This matrix has the following properties:

  • Integers in each row are sorted from left to right.
  • The first integer of each row is greater than the last integer of the previous row.

二分搜索,以整个数组尺寸作为搜索范围。
每次搜索中间值,如等于target则返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int left = 0;
int right = (matrix.length * matrix[0].length) - 1;
while(left <= right){
int mid = left + (right - left)/2;
int row = mid / matrix[0].length;
int col = mid % matrix[0].length;
if(matrix[row][col] == target){
return true;
}
else if(matrix[row][col] > target){
right = mid - 1;
}
else{
left = mid + 1;
}
}
return false;
}
}

双指针,先搜索到合适的行。
再搜索到合适的列。

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
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int i = 0;
int j = 0;

while(i < matrix.length){
if(matrix[i][0] == target){
return true;
}
else if(matrix[i][0] < target){
i++;
}
else{
break;
}
}
if( i == 0 ){
return false;
}
i--;
while(j < matrix[0].length){
if(matrix[i][j] == target){
return true;
}
j++;
}
return false;
}
}

36. Valid Sudoku

问题
Determine if a 9 x 9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules:

  1. Each row must contain the digits 1-9 without repetition.
  2. Each column must contain the digits 1-9 without repetition.
  3. Each of the nine 3 x 3 sub-boxes of the grid must contain the digits 1-9 without repetition.

Note:

  • A Sudoku board (partially filled) could be valid but is not necessarily solvable.
  • Only the filled cells need to be validated according to the mentioned rules.

遍历并创建三组不同的哈希表,每个表内包含一组哈希集合。
如果访问的元素已在哈希集合内,则返回false

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
class Solution {
public boolean isValidSudoku(char[][] board) {
HashMap<Integer,HashSet<Character>> rowMap = new HashMap<Integer,HashSet<Character>>();
HashMap<Integer,HashSet<Character>> colMap = new HashMap<Integer,HashSet<Character>>();
HashMap<Integer,HashSet<Character>> blockMap = new HashMap<Integer,HashSet<Character>>();

for (int i = 0; i < board[0].length; i++ ){
for (int j = 0; j < board.length; j++ ){
char curChar = board[i][j];
if (curChar == '.'){
continue;
}
if (!rowMap.containsKey(i)){
rowMap.put(i, new HashSet<Character>());
}
if (!colMap.containsKey(j)){
colMap.put(j, new HashSet<Character>());
}
if (!blockMap.containsKey(j/3*3+i/3)){
blockMap.put(j/3*3+i/3, new HashSet<Character>());
}
HashSet<Character> curRow = rowMap.get(i);
HashSet<Character> curCol = colMap.get(j);
HashSet<Character> curBlock = blockMap.get(j/3*3+i/3);

if ( !curRow.contains(curChar) && !curCol.contains(curChar) && !curBlock.contains(curChar) ){
curRow.add(curChar);
curCol.add(curChar);
curBlock.add(curChar);
}
else{
return false;
}
}
}
return true;
}
}

923. 3Sum With Multiplicity

Given an integer array arr, and an integer target, return the number of tuples i, j, k such that i < j < k and arr[i] + arr[j] + arr[k] == target.

As the answer can be very large, return it modulo 109 + 7.

首先遍历元素,根据元素的值和出现次数建立哈希表。
然后再哈希表中选择三个元素,如果和等于target,则计算三个元素出现次数的乘积。
最后除以重复计算的次数。
由于数值较大,因此中途计算应该采用长整型long。

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
51
52
53
54
55
class Solution {
public int threeSumMulti(int[] arr, int target) {
//enumberate every element and put them into the map
HashMap<Integer, Long> map = new HashMap<Integer, Long>();
long count = 0;

for ( int num : arr ){
if (!map.containsKey(num)){
map.put(num, (long)1);
}
else{
map.put(num, map.get(num)+1);
}
}

//traverse whole elements and select three numbers

for ( int a : map.keySet() ){
long totalA = map.get(a);
for (int b : map.keySet()){
long totalB = map.get(b);
if ( a == b ){
if (totalB < 2){
continue;
}
totalB = totalB - 1;
}

int c = target - a - b;
if ( map.containsKey(c) ){
long totalC = map.get(c);
long total = 0;
if ( a == b && b == c ){
total = totalA * totalB * ( totalC - 2 ) ;
}
else if ( b == c || a == c ){
total = totalA * totalB * ( totalC - 1 ) ;
}
else{
total = totalA * totalB * totalC;
}
if ( total > 0 ){
count += total;
}

}
}
}
count/=6;
int ans = (int) (count % 1000000007);

return ans;
}
}

11. Container With Most Water

问题
You are given an integer array height of length n. There are n vertical lines drawn such that the two endpoints of the ith line are (i, 0) and (i, height[i]).
Find two lines that together with the x-axis form a container, such that the container contains the most water.
Return the maximum amount of water a container can store.
Notice that you may not slant the container.

双指针在首尾,二者容量取决于两者中较小的一个。
贪心算法,保留两个指针上较大的元素,移动较小一边的指针。
由于指针移动时距离只会减小,因此当新的元素比上一个更大时才有可能比之前的容量更大。
遍历一次找到最大容量。
时间复杂度:O(n)

感觉这个移动有点博弈论的味了,每次都移动自己最差的一边,虽然可能变得更差,但是总比不动(或者减小)强,动最差的部分可能找到更好的结果,但是动另一边总会更差或者不变,兄弟们,这不是题,这是人生,逃离舒适圈!!(这解释我觉得无敌了,哈哈哈)

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
class Solution {
public int maxArea(int[] height) {
int best = 0;

int i = 0;
int j = height.length - 1;

while ( i < j ){
int product = 0;
if (height[i] < height[j]){
product = height[i] * ( j -i );
i++;
}
else{
product = height[j] * ( j -i );
j--;
}
if ( product > best){
best = product;
}
}
return best;
}
}

167. Two Sum II - Input Array Is Sorted

问题描述
Given a 1-indexed array of integers numbers that is already sorted in non-decreasing order, find two numbers such that they add up to a specific target number. Let these two numbers be numbers[index1] and numbers[index2] where 1 <= index1 < index2 <= numbers.length.

Return the indices of the two numbers, index1 and index2, added by one as an integer array [index1, index2] of length 2.

The tests are generated such that there is exactly one solution. You may not use the same element twice.

Your solution must use only constant extra 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
class Solution {
public int[] twoSum(int[] numbers, int target) {
int i = 0;
int j = numbers.length - 1;
int[] ans = new int[2];

while( i < j ){
int diff = target - numbers[j];
if ( diff == numbers[i]){
ans[0] = i+1;
ans[1] = j+1;
return ans;
}
else if ( diff < numbers[i] ) {
j--;
}
else{
i++;
}
}
return ans;
}
}

31. Next Permutation

A permutation of an array of integers is an arrangement of its members into a sequence or linear order.

For example, for arr = [1,2,3], the following are considered permutations of arr: [1,2,3], [1,3,2], [3,1,2], [2,3,1].

The next permutation of an array of integers is the next lexicographically greater permutation of its integer. More formally, if all the permutations of the array are sorted in one container according to their lexicographical order, then the next permutation of that array is the permutation that follows it in the sorted container. If such arrangement is not possible, the array must be rearranged as the lowest possible order (i.e., sorted in ascending order).

For example, the next permutation of arr = [1,2,3] is [1,3,2].
Similarly, the next permutation of arr = [2,3,1] is [3,1,2].
While the next permutation of arr = [3,2,1] is [1,2,3] because [3,2,1] does not have a lexicographical larger rearrangement.
Given an array of integers nums, find the next permutation of nums.

The replacement must be in place and use only constant extra memory.

从数组末尾开始遍历第i个元素。
如果后一项小于前一项,则排序关系正确。
反之则将i与遍历过的部分中比i大的第一个数字交换。
然后对已遍历的部分排序。

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
class Solution {
public void nextPermutation(int[] nums) {
int flag = 0; //标记,如果没有下一个排列时,排序数组。
if (nums.length != 1){
int i = nums.length -2;
while (i >= 0){
if (nums[i + 1] <= nums[i]) { //从尾部开始,比较元素是否是大到小
i--;
continue;
}
else { //排序关系不正确时
for (int j = nums.length-1;j>i;j--){
if (nums[j] <= nums[i]){
continue;
}
int temp = nums[j]; //将i元素和遍历过的元素中第一个比nums[i]大的交换。
nums[j] = nums[i];
nums[i] = temp;
Arrays.sort(nums,i+1,nums.length); //排序i之后的数组。
flag = 1;
break;
}
break;
}
}
if (flag == 0 ){ //如果全部从大到小,则排序整个数组。
Arrays.sort(nums);
}
}
}
}

189. Rotate Array

Given an array, rotate the array to the right by k steps, where k is non-negative.

环型替换,先求出数列长度和轮转次数的最大公约数m。
然后依次替换数列中的每个值。

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
//Rotate Array

class Solution {
public void rotate(int[] nums, int k) {
if (k != 0){
int m = gcd(nums.length,k);

for (int n = 0; n < m; n++ ) {
int i = n + k;
i %= nums.length;

int temp = nums[n];
while( true ){
int tempI = nums[i];
nums[i] = temp;
temp = tempI;

i += k;
i %= nums.length;

if (i == n){
nums[n] = temp;
break;
}
}
}
}
}

private int gcd(int a, int b){
int max = a;
int min = b;
if (max == min){
return min;
}

if ( a < b ){
max = b;
min = a;
}

return gcd(max - min, min);
}
}