日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

array专题6

發布時間:2023/12/10 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 array专题6 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

78. Subsets

思路1:深度優先搜索:每個位置都有選,和 不選兩種選擇。退出條件是下標出界。

public List<List<Integer>> subsetsV3(int[] nums) {List<List<Integer>> result = new ArrayList<List<Integer>>();List<Integer> list = new ArrayList<Integer>();dfs(result, list, nums, 0);return result;}private void dfs(List<List<Integer>> result, List<Integer> list, int[] nums, int idx) {if(idx==nums.length){result.add(new ArrayList<Integer>(list));return;}dfs(result, list, nums, idx+1);list.add(nums[idx]);dfs(result, list, nums, idx+1);list.remove(list.size()-1);}

思路2:使用位操作。有一個二進制數組,對應數組中每個元素是不是選擇。例如數組[1,2,3],有一個二進制數組[0,0,0]表示一個元素都不選擇;[0,0,1]選擇nums[0]元素;[0,1,0]選擇nums[1]元素;依次….

public List<List<Integer>> subsetsV2(int[] nums) {List<List<Integer>> result = new ArrayList<List<Integer>>();int n = nums.length;int total = (1 << n) - 1;// 2^n-1for (int i = 0; i <= total; i++) {List<Integer> list = new ArrayList<Integer>();for(int j=0;j<n;j++){if(((i>>j) &1)==1){list.add(nums[j]);}}result.add(list);}return result;}

代碼

90. Subsets II

思路:與78的深度優先搜索思路相同,只是要自己試試看哪些情況下出現重復的情況,在深度優先搜索過程中去掉這些情況。
代碼

729 My Calendar I

思路:挨個比較
學習:放在map中,floorKey(key):比key小的最大值,ceilingKey(key):比key大的最小的值
代碼

611 Valid Triangle Number

思路:這道題目首先會想到用深度優先搜索。每個位置的元素可以選擇或者不選擇。這樣肯定能解決,問題是會超時。這時候肯定是需要觀察,找規律。很遺憾,我沒找到規律。
學習:條件是:三角形任意兩邊之和>第三邊。如果兩個小的邊的和>最長的邊,那一定符合要求。先確定最大的邊:數組排序,下標最大的就是最大的邊。
例如數組[2,2,3,4]。如果i=3,接著使用兩個指針l=0,r=2;如果nums[0]+nums[2]>nums[3],那么,保持r不變,不斷增加l,直到l=r,那這個過程中所有的nums[l]+nums[r]>nums[i]。所以這中間的組合有r-l個。具體來說就是:因為nums[0]+nums[2]>nums[3]符合要求,那么nums[1]+nums[2]>nums[3]肯定符合要求,所以組合數有r-l=2-0=2個。
代碼

526 Beautiful Arrangement

思路:深度優先搜索,對于第i個位置,枚舉可能使用的數值。可能使用的數值需要滿足兩個條件: 1 還未被使用;2 能夠使得 數值%i=0或者 i%數值=0
學習:思路相同,但是迭代次數更少。
技巧一: backtracing從后面開始,這樣每個搜索在失敗之前都不會太深,因為較小的數字有更大的機會在他們自己之間被分割。解釋是這樣的。如果start從小到大,假如 start=1,nums[1]=4 ,那么4%1=0成立;start=4,nums[4]=3,那么4%3=0 或者 3%3=0都不成立;如果start從大到小,假如start=4, nums[4]=3,那么4%3=0 或者 3%3=0都不成立;則就不可能再去判斷 nums[4]=3情況下: start=3,2,1的情況了,這樣就會減少調用次數。
技巧二:Also I don’t use “visited” boolean array but use swap of an array of 1~N to avoid duplication.第start位能夠選擇的數字在nums[1~start]這些位置上的數字選擇,每當選擇一個,就把這個數字放在nums[start]位置上。這樣別的位置就不能再選擇這個數字了。聰明。

public int countArrangementV2(int N) {if (N == 0)return 0;int[] nums = new int[N + 1];for (int i = 0; i <= N; i++)nums[i] = i;helper(nums, N);return count;}private void helper(int[] nums, int start) {if (start == 0) {count++;return;}for (int i = start; i > 0; i--) {swap(nums, start, i);if (nums[start] % start == 0 || start % nums[start] == 0)helper(nums, start - 1);swap(nums, i, start);}}private void swap(int[] nums, int i, int j) {int tmp = nums[i];nums[i] = nums[j];nums[j] = tmp;}

代碼

667 Beautiful Arrangement II

思路:深度優先搜索,為每個位置上取值,再判斷是否符合條件。超時。繼續觀察。想到差值最小是1,最大是n-1.如果 k<n?1k<n?1怎么處理?我想到的是隨機取。然后就思考不下去了。
學習:如果 k<n?1k<n?1,那就先取k-1個差值:n-1,n-2….,最后的一個差值取1。
1,n,2,n-1,3,n-2,4… ==> Diff: n-1, n-2, n-3, n-4, n-5… k個數有k-1個不同的差值。
例如n=9,k=5,則取數據:1 9 2 8 3 4 5 6 7
例如n=9,k=6,則取數據:1 9 2 8 3 7 6 5 4
代碼

238 Product of Array Except Self

思路:這道題目如果允許除法,很簡單;如果是O(n^2)也很簡單。所有數相乘,只是不乘以對應下標中nums[i]這個數。但是當要求不用除法,O(n)時間復雜度,就沒有思路了。
給定數組nums={2,3,4,5}。
結果應該是:

Number2345
結果1*3*4*52*1*4*52*3*1*52*3*4*1

我思考到這里,就不知道該怎么做了。

學習:學習了一個思路,太鬼才了。在上面的表格中按1分隔,分為從左邊乘和從右邊乘。
考慮下標i=2,結果應該是2*3*1*5。這個結果可以看做是左邊的2*3,和右邊的5相乘得到的結果。

Number2345
左邊22*32*3*4
右邊5*4*35*45

把空的地方填上1

Number2345
左邊122*32*3*4
右邊5*4*35*451

通過兩次循環實現。
如果能看到2*3*4=4*3*2也許能想到從右向左。如果能看到以1分隔,分別是nums[i]左邊的數字和右邊的數字相乘,也許能想到解決方法把。

public int[] productExceptSelf(int[] nums) {int[] result = new int[nums.length];int left = 1;for (int i = 1; i <= nums.length; i++) {result[i-1] = left;left *= nums[i - 1];}int right = 1;for (int i = nums.length - 1; i >= 0; i--) {if(i<nums.length-1){right = right * nums[i+1];}result[i] = result[i] * right;}return result;}

代碼

565 Array Nesting

思路:像環的檢測, Floyd環之前做過。最簡單:把每個i遍歷一次,比較長度 。做完之后打印一下環,發現一個環內的元素無論從哪個元素開始,得到的長度都相同。例如nums=[5,4,0,3,1,6,2]。對于{5, 6, 2, 0}這樣一個環,從下標0開始,長度是4;從下標2開始,長度還是4。所以需要去重,訪問過的就不再訪問了。提交后發現超時。
學習:這個時候我又在想我的思路錯了?是不是還有更好的思路。看了討論,發現是在去重那里優化。不需要用額外的空間存儲是否訪問過;訪問過的可以標記為-1,因為初始每個元素是在[0,N-1]之間的。
改進的時候有兩種:第一計算方式需要改進,這個時候需要重新觀察數據。例如238。第二種是去重方式可以優化。例如本題。
學習2:本題還有用并查集解決的。
nums=[5,4,0,3,1,6,2]

index0123456
nums5403162
parent0123456
rank0000000

union(0,5):5的父節點是0:parent[5]=0;

index0123456
nums5403162
parent0123406
rank1000000

union(1,4):4的父節點是1:parent[4]=1;

index0123456
nums5403162
parent0123106
rank1100000

union(2,0):0的父節點是2:rootP=2,rootQ=0,rank[rootQ] > rank[rootP]=>parent[rootP] = rootQ;

index0123456
nums5403162
parent0103106
rank1100000

union(3,3):3的父節點是3:parent[3]=3;

index0123456
nums5403162
parent0103106
rank1100000

union(4,1):1的父節點是4:parent[1]=4,parent[4]=1 return;

index0123456
nums5403162
parent0103106
rank1100000

union(5,6):6的父節點是5:parent[6]=6,parent[5]=0 rank[rootQ] < rank[rootP] =>parent[6]=0

index0123456
nums5403162
parent0103100
rank1100000

union(6,2): rootP=0,rootQ=0

index0123456
nums5403162
parent0103100
rank1100000

最終有4處的parent都是0,所以長度為4,是最長的環。

[代碼]

(https://github.com/Emma123456/leetcodepractice/blob/master/src/array/ArrayNesting565.java)

769 Max Chunks To Make Sorted

思路:刷leetcode,簡直就是在找虐。我想到了,題目要求返回最多的分區數量。那如果每個都可以單獨分開是最好的。但是不可以。例如nums=[1,0,2,3,4],0和1分開的話,排序就不對了,所以0和1必須在一起。那就是說,如果在當前位置i,如果arr[i+1]以及之后的數字都大于0到i位置的元素,那么就能分隔。這樣的話,需要O(n^2)的復雜度。應該可以簡化。
學習1:因為所有左邊的元素 < 右邊元素的時候可以形成新的分區,也就是說如果對于i下標:左邊元素的最大值 <<<script type="math/tex" id="MathJax-Element-8"><</script> (i+1)到(n-1)位置的最小元素 =>可以形成新的分區。學習到的思路就是:用maxOfLeft數組,記錄當當前位置最大值;而不是拿一個變量找全局最大值。

public int maxChunksToSorted(int[] arr) {int n = arr.length;int[] maxOfLeft = new int[n];maxOfLeft[0] = arr[0];for (int i = 1; i < n; i++) {maxOfLeft[i] = Math.max(arr[i], maxOfLeft[i - 1]);}int[] minOfRight = new int[n];minOfRight[n - 1] = arr[n - 1];for (int i = n - 2; i >= 0; i--) {minOfRight[i] = Math.min(arr[i], minOfRight[i + 1]);}int chunksCount = 0;for (int i = 0; i < n - 1; i++) {if (maxOfLeft[i] <= minOfRight[i + 1])chunksCount++;}return chunksCount + 1;}

學習2:用一個max數組保存到當前位置最大的元素,每個位置的最大元素和已經排序好的數組中的元素比較,如果max[i] = sorted[i],那在這個位置就可以分割。

nums:10234
max:11234
排序好的數組:01234
下標:01234

在題目中說明arr[i] 在 [0,arr.length - 1]所以排序后的數組一定是0,1,2,….n-1。就可以進一步省略max數組,只需要max變量。這里就是重點理解 max==i。max是到目前位置的最大值;i是排序好以后i位置元素的值。

public int maxChunksToSortedV2(int[] arr) {int count = 0;int max = -1;for (int i = 0; i < arr.length; i++) {max = Math.max(max, arr[i]);if (max == i) {count++;}}return count;}

代碼

總結

以上是生活随笔為你收集整理的array专题6的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。