Skip to content

Commit 384e741

Browse files
committed
2D
2D
1 parent 8581be1 commit 384e741

File tree

7 files changed

+692
-10
lines changed

7 files changed

+692
-10
lines changed

Array/2D.md

+300
Original file line numberDiff line numberDiff line change
@@ -406,3 +406,303 @@ public class Solution {
406406
}
407407
}
408408
~~~
409+
410+
# Binary Index Tree and Segment Tree
411+
## 303. Range Sum Query - Immutable (Easy)
412+
Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.
413+
414+
Example:
415+
~~~
416+
Given nums = [-2, 0, 3, -5, 2, -1]
417+
418+
sumRange(0, 2) -> 1
419+
sumRange(2, 5) -> -1
420+
sumRange(0, 5) -> -3
421+
~~~
422+
423+
Note:
424+
You may assume that the array does not change.
425+
There are many calls to sumRange function.
426+
427+
#### Solution
428+
Easy one.
429+
430+
**注意生成sum数组时,int[] sums = new int[len + 1], 和edge cases的处理**
431+
432+
~~~
433+
public class NumArray {
434+
435+
int[] sums;
436+
437+
public NumArray(int[] nums) {
438+
if (nums == null || nums.length == 0) return;
439+
440+
this.sums = new int[nums.length + 1];
441+
sums[0] = 0;
442+
for (int i = 1; i < nums.length + 1; i++) {
443+
sums[i] = nums[i - 1] + sums[i - 1];
444+
}
445+
}
446+
447+
public int sumRange(int i, int j) {
448+
if (i < 0) i = 0;
449+
if (j >= sums.length - 1) j = sums.length - 2;
450+
451+
return sums[j + 1] - sums[i];
452+
}
453+
}
454+
455+
/**
456+
* Your NumArray object will be instantiated and called as such:
457+
* NumArray obj = new NumArray(nums);
458+
* int param_1 = obj.sumRange(i,j);
459+
*/
460+
~~~
461+
462+
## 307. Range Sum Query - Mutable
463+
Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.
464+
465+
The update(i, val) function modifies nums by updating the element at index i to val.
466+
Example:
467+
~~~
468+
Given nums = [1, 3, 5]
469+
470+
sumRange(0, 2) -> 9
471+
update(1, 2)
472+
sumRange(0, 2) -> 8
473+
~~~
474+
Note:
475+
The array is only modifiable by the update function.
476+
You may assume the number of calls to update and sumRange function is distributed evenly.
477+
478+
#### Solution
479+
1. 这题简单的方法很容易想到,但是面临的代价是要么update O(n),getSum O(1);要么update O(1), getSum O(n), 题目中说明You may assume the number of calls to update and sumRange function is distributed evenly, 如何做到update和getSum两个操作的耗时even是关键
480+
2. 这题引入两个数据结构segment tree和BIT, geeksforgeeks网站上有很好的解释,这样可以把getSum和update的复杂度都讲到O(logn)
481+
482+
###### Segment Tree
483+
类似于二分,根节点存[0-n]的sum, 然后分成左右子树,左结点存[0-n/2]的sum,右结点错[n/2-n]的sum,然后递归生成左右子树。<br>
484+
**复杂度分析,初期建树,总共有O(2n-1)个结点,space O(2n-1), time O(2n-1)**;每次查询和更新的复杂度都是O(logn)
485+
486+
###### BIT
487+
1. The idea of BIT is that every positive integer can be represented using power of 2, e.g. 12 can be represented as 8 + 4. So, if we want to get the sum(0, 12), what we can do is sum(0, 8) + sum(8, 12).
488+
2. For getSum query, we can build BIT that the parent of a node (i) is with index i - (i & (-i)), e.g. the parent index of node(12) is 8. The value of every node is the sum from its parent (exclusive) to the the node (inclusive), e.g. node(12) has a value of sum(9, 12). Therefore, for getSum(12), we add up node with index 12, and parent nodes index - (index & (-index))
489+
3. For update operation, e.g. if we update num[0], we need to update all nodes have value range from 0 to itself, let's say it is a array of length 12, so we need to update node(1), node(2), node(4), node(8). Therefore, for update(0), the starting index is node(1), and we will also update all nodes with index + (index & (-index)).
490+
491+
BIT cost O(n + 1) space, and build tree cost O(nlogn) time. Each update and getSum is O(logn)
492+
493+
Attempts: 4
494+
~~~
495+
public class NumArray {
496+
private int[] nums;
497+
private int[] BIT;
498+
499+
public NumArray(int[] nums) {
500+
if (nums == null || nums.length == 0) return;
501+
int n = nums.length;
502+
this.nums = new int[n];
503+
BIT = new int[n + 1];
504+
for (int i = 0; i < n; i++) {
505+
update(i, nums[i]);
506+
}
507+
}
508+
509+
public void update(int i, int val) {
510+
int diff = val - nums[i];
511+
nums[i] = val;
512+
for (int j = i + 1; j < BIT.length; j += j & (-j)) {
513+
BIT[j] += diff;
514+
// System.out.println(BIT[j]);
515+
}
516+
}
517+
518+
public int sumRange(int i, int j) {
519+
if (i < 0) i = 0;
520+
if (j > nums.length) j = nums.length - 1;
521+
return sumRangeHelper(j) - sumRangeHelper(i) + nums[j];
522+
}
523+
524+
private int sumRangeHelper(int i) {
525+
int sum = 0;
526+
for (int j = i; j > 0; j -= j & (-j)) {
527+
sum += BIT[j];
528+
}
529+
return sum;
530+
}
531+
}
532+
533+
/**
534+
* Your NumArray object will be instantiated and called as such:
535+
* NumArray obj = new NumArray(nums);
536+
* obj.update(i,val);
537+
* int param_2 = obj.sumRange(i,j);
538+
*/
539+
~~~
540+
541+
## 304. Range Sum Query 2D - Immutable
542+
Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2).
543+
544+
Range Sum Query 2D
545+
The above rectangle (with the red border) is defined by (row1, col1) = (2, 1) and (row2, col2) = (4, 3), which contains sum = 8.
546+
547+
Example:
548+
~~~
549+
Given matrix = [
550+
[3, 0, 1, 4, 2],
551+
[5, 6, 3, 2, 1],
552+
[1, 2, 0, 1, 5],
553+
[4, 1, 0, 1, 7],
554+
[1, 0, 3, 0, 5]
555+
]
556+
557+
sumRegion(2, 1, 4, 3) -> 8
558+
sumRegion(1, 1, 2, 2) -> 11
559+
sumRegion(1, 2, 2, 4) -> 12
560+
~~~
561+
562+
#### Solution
563+
1. 注意生成2D的sums数组长宽分别+1
564+
565+
Attempts: 2 (处理edge cases花了些时间,面试的时候和面试官确认)
566+
~~~
567+
public class NumMatrix {
568+
569+
int[][] sums;
570+
571+
public NumMatrix(int[][] matrix) {
572+
// edge case
573+
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
574+
sums = new int[0][0];
575+
return;
576+
}
577+
578+
sums = new int[matrix.length + 1][matrix[0].length + 1];
579+
for (int i = 1; i < sums.length; i++) {
580+
for (int j = 1; j < sums[0].length; j++) {
581+
sums[i][j] = matrix[i - 1][j - 1] + sums[i - 1][j] + sums[i][j - 1] - sums[i - 1][j - 1];
582+
}
583+
}
584+
}
585+
586+
public int sumRegion(int row1, int col1, int row2, int col2) {
587+
// edge cases
588+
// You may assume that row1 ≤ row2 and col1 ≤ col2.
589+
if (sums.length == 0 || sums[0].length == 0) return 0;
590+
if (row1 < 0) row1 = 0;
591+
if (row2 < 0) return 0;
592+
if (col1 < 0) col1 = 0;
593+
if (col2 < 0) return 0;
594+
595+
if (row2 >= sums.length) row2 = sums.length - 1;
596+
if (row1 >= sums.length) return 0;
597+
if (col2 >= sums[0].length) col2 = sums[0].length - 1;
598+
if (col1 >= sums[0].length) return 0;
599+
600+
return sums[row2 + 1][col2 + 1] - sums[row1][col2 + 1] - sums[row2 + 1][col1] + sums[row1][col1];
601+
}
602+
}
603+
604+
/**
605+
* Your NumMatrix object will be instantiated and called as such:
606+
* NumMatrix obj = new NumMatrix(matrix);
607+
* int param_1 = obj.sumRegion(row1,col1,row2,col2);
608+
*/
609+
~~~
610+
611+
612+
## 308. Range Sum Query 2D - Mutable
613+
614+
Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2).
615+
616+
Range Sum Query 2D
617+
The above rectangle (with the red border) is defined by (row1, col1) = (2, 1) and (row2, col2) = (4, 3), which contains sum = 8.
618+
619+
Example:
620+
~~~
621+
Given matrix = [
622+
[3, 0, 1, 4, 2],
623+
[5, 6, 3, 2, 1],
624+
[1, 2, 0, 1, 5],
625+
[4, 1, 0, 1, 7],
626+
[1, 0, 3, 0, 5]
627+
]
628+
629+
sumRegion(2, 1, 4, 3) -> 8
630+
update(3, 2, 2)
631+
sumRegion(2, 1, 4, 3) -> 10
632+
~~~
633+
634+
Note:
635+
The matrix is only modifiable by the update function.
636+
You may assume the number of calls to update and sumRegion function is distributed evenly.
637+
You may assume that row1 ≤ row2 and col1 ≤ col2.
638+
639+
#### Solution
640+
1. 2D BIT
641+
2. 2D Segment Tree
642+
643+
Attempts: 4 注意调用getSum的边界
644+
~~~
645+
public class NumMatrix {
646+
int[][] matrix;
647+
int[][] sums;
648+
649+
public NumMatrix(int[][] matrix) {
650+
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
651+
return;
652+
}
653+
654+
this.matrix = new int[matrix.length][matrix[0].length];
655+
this.sums = new int[matrix.length + 1][matrix[0].length + 1];
656+
for (int i = 0; i < matrix.length; i++) {
657+
for (int j = 0; j < matrix[0].length; j++) {
658+
update(i, j, matrix[i][j]);
659+
}
660+
}
661+
}
662+
663+
public void update(int row, int col, int val) {
664+
// edge case
665+
if (matrix == null) return;
666+
667+
if (row < 0 || row >= matrix.length || col < 0 || col >= matrix[0].length) return;
668+
int diff = val - matrix[row][col];
669+
matrix[row][col] = val;
670+
for (int i = row + 1; i < sums.length; i += i & (-i)) {
671+
for (int j = col + 1; j < sums[0].length; j += j & (-j)) {
672+
sums[i][j] += diff;
673+
}
674+
}
675+
}
676+
677+
public int sumRegion(int row1, int col1, int row2, int col2) {
678+
// edge cases
679+
if (sums == null) return 0;
680+
// You may assume that row1 ≤ row2 and col1 ≤ col2.
681+
if (row2 < 0 || row1 >= matrix.length || col2 < 0 || col1 >= matrix[0].length) return 0;
682+
if (row1 < 0) row1 = 0;
683+
if (col1 < 0) col1 = 0;
684+
if (row2 >= matrix.length) row2 = matrix.length - 1;
685+
if (col2 >= matrix[0].length) col2 = matrix[0].length - 1;
686+
687+
return getSum(row2 + 1, col2 + 1) - getSum(row1, col2 + 1) - getSum(row2 + 1, col1) + getSum(row1, col1);
688+
689+
}
690+
691+
private int getSum(int row, int col) {
692+
int ans = 0;
693+
for (int i = row; i > 0; i -= i & (-i)) {
694+
for (int j = col; j > 0; j -= j & (-j)) {
695+
ans += sums[i][j];
696+
}
697+
}
698+
return ans;
699+
}
700+
}
701+
702+
/**
703+
* Your NumMatrix object will be instantiated and called as such:
704+
* NumMatrix obj = new NumMatrix(matrix);
705+
* obj.update(row,col,val);
706+
* int param_2 = obj.sumRegion(row1,col1,row2,col2);
707+
*/
708+
~~~

Array/Stock.md

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
## 121. Best Time to Buy and Sell Stock (Easy)
2+
Say you have an array for which the ith element is the price of a given stock on day i.
3+
4+
If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.
5+
6+
Example 1:
7+
~~~
8+
Input: [7, 1, 5, 3, 6, 4]
9+
Output: 5
10+
11+
max. difference = 6-1 = 5 (not 7-1 = 6, as selling price needs to be larger than buying price)
12+
~~~
13+
14+
Example 2:
15+
~~~
16+
Input: [7, 6, 4, 3, 1]
17+
Output: 0
18+
19+
In this case, no transaction is done, i.e. max profit = 0.
20+
~~~
21+
22+
#### Solution
23+
Time: O(n) <br>
24+
Space: O(1) <br>
25+
26+
Attempts: 1
27+
~~~
28+
public class Solution {
29+
public int maxProfit(int[] prices) {
30+
if (prices == null || prices.length == 0) return 0;
31+
int min = Integer.MAX_VALUE;
32+
int max = Integer.MIN_VALUE;
33+
int ans = 0;
34+
for (int i = 0; i < prices.length; i++) {
35+
if (prices[i] < min) {
36+
min = prices[i];
37+
max = prices[i];
38+
}
39+
if (prices[i] > max) {
40+
max = prices[i];
41+
ans = Math.max(ans, max - min);
42+
}
43+
}
44+
return ans;
45+
}
46+
}
47+
~~~

0 commit comments

Comments
 (0)