九章算法強化班ladder題目梳理


1 - Follow up in Code Interview

kth-smallest-number-in-sorted-matrix

Find the kth smallest number in at row and column sorted matrix.

[
[1 ,5 ,7],
[3 ,7 ,8],
[4 ,8 ,9],
]

注意點:

  • Comparator<Pair>的實現
  • PriorityQueue poll add
 1 import java.util.*;
 2 
 3 class Pair{
 4     public int x, y, val;
 5     public Pair(int x, int y, int val){
 6         this.x = x;
 7         this.y = y;
 8         this.val = val;
 9     }
10 }
11 
12 class PairComparator implements Comparator<Pair> {
13     public int compare(Pair a, Pair b){
14         return a.val - b.val;
15     }
16 }
17 
18 public class Solution {
19     /**
20      * @param matrix: a matrix of integers
21      * @param k: an integer
22      * @return: the kth smallest number in the matrix
23      */
24     public int kthSmallest(int[][] matrix, int k) {
25         // write your code here
26         int[] dx = {0, 1};
27         int[] dy = {1, 0};
28         int m = matrix.length;
29         int n = matrix[0].length;
30         boolean[][] visited = new boolean[m][n];
31         PriorityQueue<Pair> pq = new PriorityQueue<>(k, new PairComparator());
32         pq.add(new Pair(0, 0, matrix[0][0]));
33 
34         for (int i = 0; i < k - 1; i++){
35             Pair cur = pq.poll();
36             for (int j = 0; j < 2; j++){
37                 int x = cur.x + dx[j];
38                 int y = cur.y + dy[j];
39                 if (x < m && y < n && !visited[x][y]){
40                     pq.add(new Pair(x, y, matrix[x][y]));
41                     visited[x][y] = true;
42 
43                 }
44             }
45         }
46         return pq.peek().val;
47     }
48 }
View Code

 

minimum-size-subarray-sum

Given an array of n positive integers and a positive integer s, find the minimal length of a subarray of which the sum ≥ s. If there isn't one, return -1 instead.

注意點:

  • 對於當前i,找到j使得i~j>=s,對於下一個i,j不需要回退到i(題目性質),所以可以在O(n)時間復雜度內得到解
 1 public class Solution {
 2     /**
 3      * @param nums: an array of integers
 4      * @param s: an integer
 5      * @return: an integer representing the minimum size of subarray
 6      */
 7     public int minimumSize(int[] nums, int s) {
 8         // write your code here
 9         if (nums == null || nums.length == 0) return -1;
10         int result = -1;
11         int j = 0;
12         int sum = 0;
13         for (int i = 0; i < nums.length; i++){
14             boolean flag = false;
15             if (i > 0){
16                 sum -= nums[i - 1];
17                 flag = true;
18             }
19             while (j < nums.length){
20                 if (!flag) {
21                     sum += nums[j];
22                 }
23                 else {
24                     flag = false;
25                 }
26                 if (sum >= s){
27                     if (result == -1 || j - i + 1 < result){
28                         result = j - i + 1;
29                     }
30                     break;
31                 }
32                 j++;
33             }
34         }
35         return result;
36     }
37 }
View Code

 

longest-substring-without-repeating-characters

Given a string, find the length of the longest substring without repeating characters.

注意點:

  • 使用一個map記錄各個字母出現次數
 1 import java.util.*;
 2 public class Solution {
 3     /**
 4      * @param s: a string
 5      * @return: an integer
 6      */
 7     public int lengthOfLongestSubstring(String s) {
 8         // write your code here
 9         int result = 0;
10         if (s == null || s.length() == 0){
11             return result;
12         }
13         Map<Character, Integer> map = new HashMap<>();
14         int j = 0;
15         for (int i = 0; i < s.length(); i++){
16             if (i > 0){
17                 map.put(s.charAt(i - 1), map.get(s.charAt(i - 1)) - 1);
18                 if (map.get(s.charAt(i - 1)) == 0){
19                     map.remove(s.charAt(i - 1));
20                 }
21             }
22             while(j < s.length()){
23                 if (map.containsKey(s.charAt(j))){
24                     break;
25                 }
26                 else {
27                     map.put(s.charAt(j), 1);
28                     if (map.entrySet().size() > result){
29                         result = map.entrySet().size();
30                     }
31                     j++;
32                 }
33             }
34         }
35         return result;
36     }
37 }
View Code

 

longest-substring-with-at-most-k-distinct-characters

Given a string s, find the length of the longest substring T that contains at most k distinct characters.

注意:

  • map.entrySet().size() > k 判斷鍵的個數也可以用keySet
 1 public class Solution {
 2     /**
 3      * @param s : A string
 4      * @return : The length of the longest substring
 5      *           that contains at most k distinct characters.
 6      */
 7     public int lengthOfLongestSubstringKDistinct(String s, int k) {
 8         // write your code here
 9         int result = 0;
10         if (s == null || s.length() == 0){
11             return result;
12         }
13         Map<Character, Integer> map = new HashMap<>();a
14         int j = 0;
15         for (int i = 0; i < s.length(); i++){
16             boolean flag = false;
17             if (i > 0){
18                 map.put(s.charAt(i - 1), map.get(s.charAt(i - 1)) - 1);
19                 if (map.get(s.charAt(i - 1)) == 0){
20                     map.remove(s.charAt(i - 1));
21                 }
22                 flag = true;
23             }
24             while(j < s.length()){
25                 if(!flag){
26                     if (map.containsKey(s.charAt(j))){
27                         map.put(s.charAt(j), map.get(s.charAt(j)) + 1);
28                     }
29                     else{
30                         map.put(s.charAt(j), 1);
31                     }
32                 }
33                 else {
34                     flag = false;
35                 }
36                 if (map.entrySet().size() > k){
37                     break;
38                 }
39                 else {
40                     if (j - i + 1 > result){
41                         result = j - i + 1;
42                     }
43                     j++;
44                 }
45             }
46         }
47         return result;
48     }
49 }
View Code

 

kth-smallest-sum-in-two-sorted-arrays

Given two integer arrays sorted in ascending order and an integer k. Define sum = a + b, where a is an element from the first array and b is an element from the second one. Find the kth smallest sum out of all possible sums.

注意點:

  • 把這兩個數組的和,看成一個矩陣,就變成kth-smallest-number-in-sorted-matrix了
 1 import java.util.*;
 2 
 3 class Pair{
 4     public int x, y, val;
 5     public Pair(int x, int y, int val){
 6         this.x = x;
 7         this.y = y;
 8         this.val = val;
 9     }
10 }
11 
12 class PairComparator implements Comparator<Pair>{
13     public int compare(Pair a, Pair b){
14         return a.val - b.val;
15     }
16 }
17 
18 
19 public class Solution {
20     /**
21      * @param A an integer arrays sorted in ascending order
22      * @param B an integer arrays sorted in ascending order
23      * @param k an integer
24      * @return an integer
25      */
26     public int kthSmallestSum(int[] A, int[] B, int k) {
27         // Write your code here
28         int[] dx = {0, 1};
29         int[] dy = {1, 0};
30         int m = A.length;
31         int n = B.length;
32         boolean[][] visited = new boolean[m][n];
33         PriorityQueue<Pair> pq = new PriorityQueue<>(k, new PairComparator());
34         pq.add(new Pair(0, 0, A[0] + B[0]));
35         for (int i = 0; i < k - 1; i++){
36             Pair cur = pq.poll();
37             for(int j = 0; j < 2; j++){
38                 int x = cur.x + dx[j];
39                 int y = cur.y + dy[j];
40                 if (x < m && y < n && !visited[x][y]){
41                     visited[x][y] = true;
42                     pq.add(new Pair(x, y, A[x] + B[y]));
43                 }
44             }
45         }
46         return pq.peek().val;
47     }
48 }
View Code

 

kth-largest-in-n-arrays

Find K-th largest element in N arrays.

N個數組找第K大

 1 import java.util.*;
 2 
 3 class Item{
 4     public int val, index, array;
 5     public Item(int val, int index, int array){
 6         this.val = val;
 7         this.index = index;
 8         this.array = array;
 9     }
10 }
11 
12 class ItemComparator implements Comparator<Item>{
13     public int compare(Item a, Item b){
14         return b.val - a.val;
15     }
16 }
17 
18 public class Solution {
19     /**
20      * @param arrays a list of array
21      * @param k an integer
22      * @return an integer, K-th largest element in N arrays
23      */
24     public int KthInArrays(int[][] arrays, int k) {
25         // Write your code here
26         PriorityQueue<Item> pq = new PriorityQueue<>(k, new ItemComparator());
27         for (int i = 0; i < arrays.length; i++){
28             Arrays.sort(arrays[i]);
29             if (arrays[i].length > 0){
30                 pq.add(new Item(arrays[i][arrays[i].length - 1], arrays[i].length - 1, i));
31             }
32         }
33         for (int i = 0; i < k - 1; i++){
34             Item item = pq.poll();
35             if (item.index > 0){
36                 pq.offer(new Item(arrays[item.array][item.index - 1], item.index - 1, item.array));
37             }
38         }
39         return pq.peek().val;
40     }
41 }
View Code

 

two-sum-less-than-or-equal-to-target

Given an array of integers, find how many pairs in the array such that their sum is less than or equal to a specific target number. Please return the number of pairs.

找小於等於target的pairs數

注意點:

  • 先排序
  • 兩根指針移動時,可以根據兩根指針的和,得到一個范圍的解
 1 import java.util.*;
 2 public class Solution {
 3     /**
 4      * @param nums an array of integer
 5      * @param target an integer
 6      * @return an integer
 7      */
 8     public int twoSum5(int[] nums, int target) {
 9         // Write your code here
10         int result = 0;
11         if (nums == null || nums.length < 2){
12             return result;
13         }
14         Arrays.sort(nums);
15         int left = 0;
16         int right = nums.length - 1;
17         while (left < right){
18             if (nums[left] + nums[right] <= target){
19                 result += right - left;
20                 left++;
21             }
22             else{
23                 right--;
24             }
25         }
26         return result;
27     }
28 }
View Code

 

triangle-count

Given an array of integers, how many three numbers can be found in the array, so that we can build an triangle whose three edges length is the three numbers that we find?

上一題的變形題,先排序,固定最后一個元素,找前面大於target的pairs數

 1 import java.util.*;
 2 public class Solution {
 3     /**
 4      * @param S: A list of integers
 5      * @return: An integer
 6      */
 7     public int triangleCount(int S[]) {
 8         // write your code here
 9         Arrays.sort(S);
10         int result = 0;
11         for(int i = S.length - 1; i > 1; i--){
12             result += twoSum(S, 0, i - 1, S[i]);
13         }
14         return result;
15     }
16     
17     private int twoSum(int S[], int start, int end, int target){
18         int result = 0;
19         while (start < end){
20             if (S[start] + S[end] > target){
21                 result += end - start;
22                 end--;
23             }
24             else{
25                 start++;
26             }
27         }
28         return result;
29     }
30 }
View Code

 

minimum-window-substring

Given a string source and a string target, find the minimum window in source which will contain all the characters in target.

擁有target串所有字母(相同字母個數>=)的source中最靠近開頭的串。

兩次遍歷,先找結尾,再找開頭

 1 import java.util.*;
 2 
 3 public class Solution {
 4     /**
 5      * @param source: A string
 6      * @param target: A string
 7      * @return: A string denote the minimum window
 8      *          Return "" if there is no such a string
 9      */
10     public String minWindow(String source, String target) {
11         // write your code
12         if (source.length() == 0 || target.length() == 0) return "";
13         int startIndex = 0;
14         int endIndex = 0;
15         Map<Character, Integer> targetMap = new HashMap<>();
16         Map<Character, Integer> sourceMap = new HashMap<>();
17         for (int i = 0; i < target.length(); i++){
18             if (!targetMap.containsKey(target.charAt(i))){
19                 targetMap.put(target.charAt(i), 1);
20             }
21             else{
22                 targetMap.put(target.charAt(i), targetMap.get(target.charAt(i)) + 1);
23             }
24         }
25         while(endIndex < source.length()){
26             if (!sourceMap.containsKey(source.charAt(endIndex))){
27                 sourceMap.put(source.charAt(endIndex), 1);
28             }
29             else{
30                 sourceMap.put(source.charAt(endIndex), sourceMap.get(source.charAt(endIndex)) + 1);
31             }
32             if (testHash(sourceMap, targetMap)){
33                 break;
34             }
35             endIndex++;
36         }
37         if (endIndex == source.length()){
38             return "";
39         }
40         while(startIndex <= endIndex){
41             sourceMap.put(source.charAt(startIndex), sourceMap.get(source.charAt(startIndex)) - 1);
42             if (sourceMap.get(source.charAt(startIndex)) == 0){
43                 sourceMap.remove(source.charAt(startIndex));
44             }
45             if (!testHash(sourceMap, targetMap)){
46                 break;
47             }
48             startIndex++;
49         }
50         return source.substring(startIndex, endIndex + 1);
51     }
52     
53     private boolean testHash(Map<Character, Integer> sourceMap, Map<Character, Integer> targetMap){
54         for (Character key : targetMap.keySet()){
55             if (!sourceMap.containsKey(key) || sourceMap.get(key) < targetMap.get(key)) {
56                 return false;
57             }
58         }
59         return true;
60     }
61 }
View Code

 

kth-smallest-numbers-in-unsorted-array

Find the kth smallest numbers in an unsorted integer array.

使用quickSelect算法:

  • i <= j; nums[x] > pivot
  • j - start >= k - 1; 第k個點落入0~j之間;quickSelect(nums, start, j, k);
  • i - start <= k - 1; 第k個點落入i~end之間;quickSelect(nums, i, end, k - i + start);
  • 第k個點落入j~i之間;返回nums[j + 1];

關於partition的理解:

  • partition之后,<=pivot的在左邊,>=pivot的在右邊,並不存在左右明確的分界線
  • 只能保證j及其左邊<=pivot,i及其右邊>=pivot。可以配合k使得搜索區域減小一半
 1 class Solution {
 2     /*
 3      * @param k an integer
 4      * @param nums an integer array
 5      * @return kth smallest element
 6      */
 7     public int kthSmallest(int k, int[] nums) {
 8         // write your code here
 9         return quickSelect(nums, 0, nums.length - 1, k);
10     }
11 
12     private int quickSelect(int[] nums, int start, int end, int k){
13         if (start >= end){
14             return nums[start];         //區間只有一個數,直接返回
15         }
16         int pivot = nums[(start + end) / 2];
17         int i = start;
18         int j = end;
19         while(i <= j){                           //i<=j,有等號
20             while(i <= j && nums[i] < pivot){         //和pivot比較沒有等號
21                 i++;
22             }
23             while(i <= j && nums[j] > pivot){
24                 j--;
25             }
26             if(i <= j){
27                 int tmp = nums[i];
28                 nums[i] = nums[j];
29                 nums[j] = tmp;
30                 i++;                             //兩個同時++ --
31                 j--;
32             }
33         }
34         if (j - start >= k - 1){              //答案落在0~j區間
35             return quickSelect(nums, start, j, k);
36         }
37         else if (i - start <= k - 1){                //答案落在i~end區間,注意k
38             return quickSelect(nums, i, end, k - i + start);
39         }
40         else {
41             return nums[j + 1];             //j和i中間隔了一個,它恰好是答案
42         }
43     }
44 }
View Code

 

kth-largest-element

Find K-th largest element in an array.

找第k大,與上題思路一樣。

 1 class Solution {
 2     /*
 3      * @param k : description of k
 4      * @param nums : array of nums
 5      * @return: description of return
 6      */
 7     public int kthLargestElement(int k, int[] nums) {
 8         // write your code here
 9         return quickSelect(nums, 0, nums.length - 1, k);
10     }
11 
12     private int quickSelect(int[] nums, int start, int end, int k){
13         if (start >= end){
14             return nums[start];
15         }
16         int pivot = nums[(start + end) / 2];
17         int i = start;
18         int j = end;
19         while (i <= j){
20             while (i <= j && nums[i] > pivot){
21                 i++;
22             }
23             while (i <= j && nums[j] < pivot){
24                 j--;
25             }
26             if (i <= j){
27                 int tmp = nums[i];
28                 nums[i] = nums[j];
29                 nums[j] = tmp;
30                 i++;
31                 j--;
32             }
33         }
34         if(j - start >= k - 1){
35             return quickSelect(nums, start, j, k);
36         }
37         else if(i - start <= k - 1){
38             return quickSelect(nums, i, end, k - i + start);
39         }
40         else{
41             return nums[j + 1];
42         }
43     }
44 };
View Code

 

2 - Data Structure I

connecting-graph

Given n nodes in a graph labeled from 1 to n. There is no edges in the graph at beginning.

You need to support the following method:
1. connect(a, b), add an edge to connect node a and node b. 2.query(a, b)`, check if two nodes are connected

並查集簡單應用,father[a] == a是這個類別的隊長

 1 public class ConnectingGraph {
 2 
 3     private int[] father = null;
 4 
 5     public ConnectingGraph(int n) {
 6         // initialize your data structure here.
 7         father = new int[n];
 8         for(int i = 0; i < n; i++){
 9             father[i] = i;
10         }
11     }
12 
13     private int find(int a){
14         if (father[a] == a){
15             return a;
16         }
17         int result = find(father[a]);
18         father[a] = result;
19         return result;
20     }
21 
22     public void connect(int a, int b) {
23         // Write your code here
24         int a_f = find(a - 1);
25         int b_f = find(b - 1);
26         father[a_f] = b_f;
27 
28     }
29 
30     public boolean  query(int a, int b) {
31         // Write your code here
32         int a_f = find(a - 1);
33         int b_f = find(b - 1);
34         return a_f == b_f;
35     }
36 }
View Code

 

connecting-graph-ii

Given n nodes in a graph labeled from 1 to n. There is no edges in the graph at beginning.

You need to support the following method:
1. connect(a, b), an edge to connect node a and node b
2. query(a), Returns the number of connected component nodes which include node a.

返回當前節點所在聯通塊的節點數。

隊長節點保存節點數,取負數作為標記。

connect時需要判斷,以免錯誤覆蓋

 1 class Pair{
 2     public int index = 0;
 3     public int result = 0;
 4 
 5     public Pair(int index, int result){
 6         this.index = index;
 7         this.result = result;
 8     }
 9 }
10 
11 public class ConnectingGraph2 {
12 
13     private int[] father = null;
14 
15     public ConnectingGraph2(int n) {
16         // initialize your data structure here.
17         father = new int[n];
18         for(int i = 0; i < n; i++){
19             father[i] = -1;
20         }
21     }
22 
23     private Pair find(int a){
24         if (father[a] < 0){
25             return new Pair(a, father[a]);
26         }
27         Pair r = find(father[a]);
28         father[a] = r.index;
29         return r;
30     }
31 
32     public void connect(int a, int b) {
33         // Write your code here
34         Pair a_f = find(a - 1);
35         Pair b_f = find(b - 1);
36         if (a_f.index != b_f.index){
37             father[a_f.index] = a_f.result + b_f.result;
38             father[b_f.index] = a_f.index;
39         }
40         // System.out.println(Arrays.toString(father));
41     }
42 
43     public int query(int a) {
44         // Write your code here
45         return -find(a - 1).result;
46     }
47 }
View Code

 

connecting-graph-iii

Given n nodes in a graph labeled from 1 to n. There is no edges in the graph at beginning.

You need to support the following method:
1. connect(a, b), an edge to connect node a and node b
2. query(), Returns the number of connected component in the graph

返回聯通塊總數,維持一個全局的count即可。

 1 public class ConnectingGraph3 {
 2 
 3     private int[] father = null;
 4     private int count = 0;
 5 
 6     public ConnectingGraph3(int n) {
 7         // initialize your data structure here.
 8         this.count = n;
 9         father = new int[n];
10         for(int i = 0; i < n; i++){
11             father[i] = i;
12         }
13     }
14 
15     private int find(int a){
16         if (father[a] == a){
17             return a;
18         }
19         int result = find(father[a]);
20         father[a] = result;
21         return result;
22     }
23 
24     public void connect(int a, int b) {
25         // Write your code here
26         int a_f = find(a - 1);
27         int b_f = find(b - 1);
28         if (a_f != b_f){
29             count--;
30         }
31         father[a_f] = b_f;
32     }
33 
34     public int query() {
35         // Write your code here
36         return count;
37     }
38 }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM