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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

位运算在一类数组题中的用法 只出现一次的数字I

發布時間:2025/3/15 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 位运算在一类数组题中的用法 只出现一次的数字I 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 前言
  • 復習
  • 一:只出現一次的數字I
  • 二:只出現一次的數字II
  • 二:只出現一次的數字III

前言

LeetCode上有幾道題特別相似,分別是leetcode 136只出現一次的數(簡單),137只出現一次的數Ⅱ(中等),260只出現一次的數Ⅲ。
這幾道題當然有很多中解法,但是其中有一種解法特別獨特,也是很多人無法想到的,那么就是利用位運算,說起位運算,其實很多人都忘記了,只是知道怎么回事,但是不知道它具體有什么用處。讀完本文,你就能感覺到它的神奇之處了

復習

既然需要使用位運算,那么在這里我們就先復習一下吧


左移和右移

一:只出現一次的數字I

題目

這道題需要借助到異或運算符對于參與運算的兩個對象,如果對應二進制位不同結果是1,否則就是0。主要使用的性質有**:0異或任何數等于任何數,任何數異或自己都等于0,異或運算滿足結合律和交換律**

所以對于上面的數組【4,1,2,1,2】,我們可以4 ^ 1 ^ 2 ^ 1 ^ 2 ,也就是4 ^ 1 ^ 1 ^ 2 ^ 2,所以4 ^ (1 ^ 1) ^ (2 ^ 2),所以4 ^ 0 ^ 0,所以結果就是4

class Solution { public:int singleNumber(vector<int>& nums) {int value=0;for(auto e : nums){value=value^e;}return value;} };

二:只出現一次的數字II

題目

對于這道題,有一種方法是自動機,但是比較難以理解,詳情可以看這篇文章的講解
但我們最常使用的還是直接用位運算

首先需要發現規律,將我們的數的二進制位每一位對應相加,然后對每一位的和進行取余

這里大家注意觀察最終取余的結果和目標值。之所以這樣做的原因是因為,如果其他書都出現了3次,只有目標數出現了1次,那么每一位為1的個數無非就是3的倍數或3的倍數+1,而3的倍數+1也就是我們要找的那個情況

代碼如下:

class Solution { public:int singleNumber(vector<int>& nums){int ret=0;for(int i=0;i<32;i++){int count=0;for(int j=0;j<nums.size();j++){if((nums[j]>>i & 1) == 1){count++;}}if(count%3!=0){ret=ret | 1 << i;}}return ret;}};

第一個for循環用于控制數字的每一個二進制位,進入第一個for循環之后,定義一個count,用來保存此時各數字對應二進制位的和,然后第二個循環首先判斷該數字的這一二進制位是否是1,判斷時只需要讓這個數字右移由i控制的位數,讓判斷的位置跑到最低位,然后與1進行與運算,因為與運算是兩者“同時是1才能是1”,所以一旦結果不等于1,說明判斷的這一位就不是1,如果是1則count++,第二個for循環結束后,所有數字對應的二進制位加和就完畢了,接著根據之前的性質判斷,如果取余不等于0,說明count是3的倍數+1,是由于那個單獨出現的數字導致的,因此ret與1進行或運算,讓其最后一位變為1(這個1就是單獨出現的數字的某一二進制位),由于之前右移了i位,所以現在讓其左移i位,回正

二:只出現一次的數字III


這道題和第一題有點相似,但是它是有兩個單獨出現的數字,如果直接使用異或,那么得到結果就是拿兩個目標數的異或值,肯定是不行的

所以我們可以這樣做,將元素分為兩組,每組包含一個目標值,然后組內異或,那么每組的最終結果就是一個目標值

比如【a,b,a,b,c,d,e,f,e,f】進行分組后,組A為:【a,a,b,b,c】,組B為:【e,e,f,f,d】,組A得到c,組B得到d。
c和d不同,所以其異或的結果一定不是0,我們只研究其最右面那一位(其實任何一位都可以),也就是讓其異或結果變為0或1,接著以0或1作為標準,讓數組內的元素進行分組,比如說異或結果是1,我就這樣判斷:和1與運算的結果為1的分為1組,為0的分為另外一組我不需要管它到底在哪一組,我只明白相同的數字肯定在一組

那么最后一點就是如何讓其異或結果變為0或1呢,假設異或結果是
temp,只需要temp & (-temp),因為負數等原數按位取反+1

class Solution { public:vector<int> singleNumber(vector<int>& nums) {int temp=0;for(auto e : nums)temp ^=e;//保留兩個不同的數的異或值unsigned int div=temp & (-(unsigned int)temp);//注意這是32位環境,注意強轉為無符號vector<int> group(2.0);for(auto e : nums){if((e & div)==0)//組內異或{group[0] ^= e;}else{group[1] ^=e;}}return group;} };

總結

以上是生活随笔為你收集整理的位运算在一类数组题中的用法 只出现一次的数字I的全部內容,希望文章能夠幫你解決所遇到的問題。

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