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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LeetCode 47全排列Ⅱ48旋转图像

發(fā)布時間:2025/3/20 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LeetCode 47全排列Ⅱ48旋转图像 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原創(chuàng)公眾號:bigsai 如果不錯記得點贊收藏!
關(guān)注回復(fù) bigsai 領(lǐng)取Java進(jìn)階pdf資源,回復(fù)進(jìn)群加入力扣打卡群。
上周打卡內(nèi)容:43字符串相乘&44通配符匹配 45跳躍游戲&46全排列

全排列Ⅱ

給定一個可包含重復(fù)數(shù)字的序列,返回所有不重復(fù)的全排列。

示例:

輸入: [1,1,2]
輸出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]

法一 哈希
這題相比之前的就是有重復(fù)的情況,最笨的方法就是用哈希將各種序列存到Set中最后返回,但是這也是一種方法和策略:

Set<String>set=new HashSet<String>();public List<List<Integer>> permuteUnique(int[] nums) {List<List<Integer>> list=new ArrayList<List<Integer>>();Arrays.sort(nums);arrange(nums, 0, nums.length-1, list);return list;}private void arrange(int[] nums, int start, int end, List<List<Integer>> list) {if(start==end){List<Integer>list2=new ArrayList<Integer>();StringBuilder sBuilder=new StringBuilder();for(int a:nums){sBuilder.append(a);list2.add(a);}if(!set.contains(sBuilder.toString())){list.add(list2); set.add(sBuilder.toString());}}for(int i=start;i<=end;i++){swap(nums,i,start);arrange(nums, start+1, end, list);swap(nums, i, start);}}private void swap(int[] nums, int i, int j) {int team=nums[i];nums[i]=nums[j];nums[j]=team;}

但是效果比較差:

法二 遞歸剪枝

第一個是真的很慢,但是有什么可以優(yōu)化的方案嗎?答案當(dāng)然是有的,我們在執(zhí)行遞歸全排列的時候,主要考的是要把重復(fù)的情況搞下去,怎么思考這個問題呢?

我們在進(jìn)行交換swap的時候從前往后,前面的確定之后就不會在動,所以我們要慎重考慮和誰交換。剩下所有數(shù)默認(rèn)不重復(fù)會排列所有情況,所以1 2 3和3 2 1在這個問題上等價,但是1 1 2 3第一個數(shù)有三種情況而不是四種情況

1 1 2 3
2 1 1 3
3 1 2 1

另外比如3 1 1,3和自己交換,和后面兩個1只能和其中一個進(jìn)行交換,我們這里可以約定和第一個出現(xiàn)的進(jìn)行交換,我們看一個圖解部分過程:

所以,當(dāng)我們從一個index開始的時候要記住以下的規(guī)則:同一個數(shù)只交換一次(包括自己的數(shù))。
在判斷的時候,你可以遍歷,也可以使用hashSet().

具體實現(xiàn)的代碼為:

public List<List<Integer>> permuteUnique(int[] nums) {List<List<Integer>> list=new ArrayList<List<Integer>>();arrange(nums, 0, nums.length-1, list);return list;}private void arrange(int[] nums, int start, int end, List<List<Integer>> list) {if(start==end){List<Integer>list2=new ArrayList<Integer>();for(int a:nums){list2.add(a);}list.add(list2);}Set<Integer>set=new HashSet<Integer>(); for(int i=start;i<=end;i++){if(set.contains(nums[i]))continue;set.add(nums[i]); swap(nums,i,start);arrange(nums, start+1, end, list);swap(nums, i, start);} } private void swap(int[] nums, int i, int j) {int team=nums[i];nums[i]=nums[j];nums[j]=team; }

法三 回溯剪枝
我是壓根沒考慮用回溯,因為回溯完整的比直接遞歸慢,但是這里用回溯剪枝比較好,剪枝條的規(guī)則如下:

  • 先對序列進(jìn)行排序
  • 試探性將數(shù)據(jù)放到當(dāng)前位置
    • 如果當(dāng)前位置數(shù)字已經(jīng)被使用,那么不可使用
    • 如果當(dāng)前數(shù)字和前一個相等但是前一個沒有被使用,那么前當(dāng)前不能使用,需要使用前一個數(shù)字。

思路很簡單,實現(xiàn)起來也很簡單:

List<List<Integer>> list; public List<List<Integer>> permuteUnique(int[] nums) {list=new ArrayList<List<Integer>>();List<Integer> team=new ArrayList<Integer>();boolean jud[]=new boolean[nums.length];Arrays.sort(nums);dfs(jud, nums, team, 0);return list; } private void dfs(boolean[] jud, int[] nums, List<Integer> team, int index) {// TODO Auto-generated method stubint len = nums.length;if (index == len)// 停止{list.add(new ArrayList<Integer>(team));} elsefor (int i = 0; i < len; i++) {if (jud[i]||(i>0&&nums[i]==nums[i-1]&&!jud[i-1])) //當(dāng)前數(shù)字被用過 或者前一個相等的還沒用,當(dāng)前即不可用continue;team.add(nums[i]);jud[i]=true;dfs(jud, nums, team, index + 1);jud[i] = false;// 還原team.remove(index);} }

旋轉(zhuǎn)圖像

題目描述:

給定一個 n × n 的二維矩陣表示一個圖像。
將圖像順時針旋轉(zhuǎn) 90 度。
說明:
你必須在原地旋轉(zhuǎn)圖像,這意味著你需要直接修改輸入的二維矩陣。請不要使用另一個矩陣來旋轉(zhuǎn)圖像。

示例 1:

給定 matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],
原地旋轉(zhuǎn)輸入矩陣,使其變?yōu)?
[
[7,4,1],
[8,5,2],
[9,6,3]
]

示例 2:

給定 matrix =
[
[ 5, 1, 9,11],
[ 2, 4, 8,10],
[13, 3, 6, 7],
[15,14,12,16]
],
原地旋轉(zhuǎn)輸入矩陣,使其變?yōu)?
[
[15,13, 2, 5],
[14, 3, 4, 1],
[12, 6, 8, 9],
[16, 7,10,11]
]

這題思路可能比較清晰,但實現(xiàn)起來磕磕絆絆的地方可能比較多。每個人按照自己的思維找到一個好的方法就可以了,我把我自己的方法分享一下:

首先要看到重要信息:

  • n*n的矩陣
  • 不可創(chuàng)建新的矩陣
  • 順時針旋轉(zhuǎn)

旋轉(zhuǎn)其實就是一個中心對稱問題找點的問題,我們可以將這個矩陣分為任意四部分,其中一個部分某個點作為起始點開始交換操作。明顯看的出來是左開右閉的操作。

在具體確定好(i,j)后,找到對應(yīng)其他三個點的坐標(biāo)。坐標(biāo)其實也是很有規(guī)律的,需要自己相通就行,這里就不帶大家推導(dǎo)了,點和對面的點中點是矩陣中心,可以進(jìn)行驗算。

實現(xiàn)代碼為:

public void rotate(int[][] matrix) {int len=matrix.length;for(int i=0;i<len/2;i++)//第i行{int team=0;for(int j=i;j<len-i-1;j++)//每個數(shù)進(jìn)行四次操作{int x1=i,y1=j;int x2=j,y2=len-i-1;int x3=len-i-1,y3=len-j-1;int x4=len-j-1,y4=i;team=matrix[x1][y1];matrix[x1][y1]=matrix[x4][y4];matrix[x4][y4]=matrix[x3][y3];matrix[x3][y3]=matrix[x2][y2];matrix[x2][y2]=team;}}}

結(jié)語:好了今天就到這里了,歡迎關(guān)注原創(chuàng)技術(shù)公眾號:【bigsai】,回復(fù)進(jìn)群加筆者微信一起加入打卡!

總結(jié)

以上是生活随笔為你收集整理的LeetCode 47全排列Ⅱ48旋转图像的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。