【算法技巧】位運算

目錄

  • 1.概述
  • 2.位運算技巧
    • 2.1.與運算 (&)
      • 2.1.1.判斷奇偶性
      • 2.1.2.判斷一個數是否是 2 的冪
      • 2.1.3.將英文字母轉換為大寫
      • 2.1.4.代替取模運算
    • 2.2.或運算 (|)
      • 2.2.1.將英文字母轉換為小寫
    • 2.3.異或運算 (^)
      • 2.3.1.消除成對相同的數
      • 2.3.2.不使用臨時變量來交換兩個數
      • 2.3.3.進行英文字母大小寫互換
      • 2.3.4.判斷兩個數是否異號
    • 2.4.取反運算 (~)
      • 2.4.1.自增
      • 2.4.2.自減
    • 2.5.移位運算 (<<、>>、>>>)
      • 2.5.1.乘以 2
      • 2.5.2.除以 2
  • 3.應用

1.概述

(1)位運算是一種直接對二進制位進行操作的運算方式。它們是在計算機中對數據的底層操作,通常在位級別上進行,不考慮數據的整體值。在 Java 中,位運算符有以下幾種:

  • 與運算 (&):對兩個操作數的每一位進行與操作,只有當對應的位都為 1 時,結果為 1,否則為 0。
  • 或運算 (|):對兩個操作數的每一位進行或操作,只要對應的位至少有一個為 1,結果為 1,否則為 0。
  • 異或運算 (^):對兩個操作數的每一位進行異或操作,只有當對應的位不同時,結果為 1,否則為 0。
  • 取反運算 (~):對一個操作數的每一位進行取反操作,將 0 變為 1,將 1 變為 0。
  • 左移運算 (<<):將一個操作數的所有位向左移動指定的位數,低位補 0。
  • 右移運算 (>>):將一個操作數的所有位向右移動指定的位數,高位的處理取決于具體情況。
  • 無符號右移運算 (>>>):將一個操作數的所有位向右移動指定的位數,高位總是補 0。

(2)位運算常用于編程中的一些特定場景,如位掩碼位集合操作優化算法設計以及操作硬件等。它們在處理位級別的數據和優化性能方面非常有用。

有關位運算的更多技巧,可以參考 Bit Twiddling Hacks。

2.位運算技巧

2.1.與運算 (&)

2.1.1.判斷奇偶性

判斷奇偶性:位運算中最低位為 1 表示奇數,為 0 表示偶數。

(n & 1) == 1	// n 為奇數
(n & 1) == 0	// n 為偶數

2.1.2.判斷一個數是否是 2 的冪

如果一個數是 2 的冪,那么它的二進制形式中只有最高位為 1,其他位都是 0。

(n & (n - 1)) == 0	// x 是 2 的冪
(n & (n - 1)) == 1	// x 不是 2 的冪

n & (n - 1) 的作用是消除數字 n 的二進制表示中的最后一個 1。因此,如果 n 是 2 的冪,那么 n 的二進制表示中只有一個 1,所以 n & (n - 1) 的結果必為 0。

2.1.3.將英文字母轉換為大寫

我們可以通過將小寫字母與下劃線 ‘_’ 進行與操作,將其轉換為對應的大寫字母。

(char) ('n' & '_') = 'N'
(char) ('N' & '_') = 'N'[添加鏈接描述](https://xgqngu.blog.csdn.net/article/details/130137431)
  • 在位運算中,字符在內存中以數字的形式表示。在大部分字符編碼中(如 ASCII 碼),大寫字母的編碼值比小寫字母的編碼值要小
  • 在 ASCII 編碼中,大寫字母和小寫字母的 ASCII 碼值之間的差值為固定的 32(或二進制的 0010 0000),例如,字母 ‘A’ 的 ASCII 碼值為 65,而字母 ‘a’ 的 ASCII 碼值為 97,它們之間的差值就是 32。
  • 而 ‘_’ 的二進制表示為 0101 1111,小寫字母 a-z 的 ASCII 值范圍為 97-122,即 0110 0001-0011 1101;
  • 那么小寫字母與 ‘_’ 相與后,相當于其對應 ASCII 值減少了 32,因此也就轉換為了對應的大寫字母

2.1.4.代替取模運算

(1)一般來說,我們要求 h 除以 n 的余數,會通過取模運算 (%),即 h % n。但當 n 是 2 的冪次方時,我們可以使用位運算來代替取模運算,從而達到提高計算效率的目的,即:

h % n == hash & (n - 1)	// n 是 2 的冪次方

(2)當 n 是 2 的冪次方時,它的二進制表示為 100…00(n 個 0)。這意味著 n - 1 的二進制表示為 011…11(n 個 1)。因此,按位與運算 h & (n - 1) 實際上是將 h 的二進制表示的最后 n 位保留,其他位都設為 0,起到了取模的效果。

(3)在這種情況下進行替換有一些具體的應用場景,例如 HashMap 中數組 table 長度被設置為 2 的 n 次方中的一個目的就是上面提到的提高計算效率,具體細節可以參考 Java 基礎——HashMap 底層數據結構與源碼分析這篇文章中的 3.1 章節。

2.2.或運算 (|)

2.2.1.將英文字母轉換為小寫

我們可以通過將大寫字母與空格 ’ ’ 進行或操作,將其轉換為對應的小寫字母。

(char) ('N' | ' ') = 'n'
(char) ('n' | ' ') = 'n'
  • 其原理與上面的通過與操作將英文字符轉換為大寫類似,空格字符在 ASCII 編碼中的值為 32(十進制),其二進制表示為 0010 0000
  • 而大寫字母 A-Z 的 ASCII 值范圍為 65-90,即 0110 0001-0011 1101
  • 那么大寫字母與 ’ ’ 相或后,相當于其對應 ASCII 值增加了 32,因此也就轉換為了對應的小寫字母

2.3.異或運算 (^)

2.3.1.消除成對相同的數

(1)異或運算有兩個非常重要的性質:

  • 一個數和 0 做異或運算的結果為它本身,即 a ^ 0 = a。
  • 一個數和它本身做異或運算結果為 0,即 a ^ a = 0;

(2)其中,第二條性質明顯有一個重要的用途,即消除成對相同的數,如果再結合異或運算的交換律,那么我們可以很迅速地解決 136.只出現一次的數字這題,即給定一個非空整數數組,除了某個元素只出現一次以外,其余每個元素均出現兩次。找出那個只出現了一次的元素

class Solution {public int singleNumber(int[] nums) {int single = 0;/*對于本題,只要把所有數字進行異或,成對的數字就會變成 0,落單的數字和 0 做異或還是它本身,所以最后異或的結果就是只出現?次的元素。*/for (int num : nums) {single ^= num;}return single;}
}

268.丟失的數字 這題也可以通過這個技巧來解決。

2.3.2.不使用臨時變量來交換兩個數

int a = -1;
int b = 2;
a ^= b;
b ^= a;
a ^= b;
System.out.println("a = " + a);     // a = 2
System.out.println("b = " + b);     // b = -1

其實,上面不使用臨時變量來交換兩個數是基于 a ^ a = 0 這一性質實現的,具體推導過程如下:

a ^= b;		// a1 = a ^ b
b ^= a;		// b1 = b ^ a1 = b ^ (a ^ b) = a
a ^= b;		// a2 = a1 ^ b1 = (a ^ b) ^ a = b

2.3.3.進行英文字母大小寫互換

(char) ('n' ^ ' ') = 'N'
(char) ('N' ^ ' ') = 'n'
  • 其原理與上面的通過與操作將英文字符轉換為大寫類似,空格字符在 ASCII 編碼中的值為 32(十進制),其二進制表示為 0010 0000
  • 而大寫字母 A-Z 的 ASCII 值范圍為 65-90,即 0110 0001-0011 1101
  • 而小寫字母 a-z 的 ASCII 值范圍為 97-122,即 0110 0001-0011 1101
  • 大小寫字母與 ’ ’ 相異后,小寫字母對應 ASCII 值減少了 32,大寫字母對應 ASCII 值增加了 32,因此也就進行了英文字母大小寫互換

2.3.4.判斷兩個數是否異號

計算機底層中整數通常使用補碼來表示,通過位運算判斷兩個數是否異號的原理是就是利用了補碼表示中最高位符號位的特性。默認情況下,整數的最高位為符號位,0 表示正數,1 表示負數。通過位運算判斷兩個數是否異號的步驟如下:

  • 對兩個數進行異或運算 (^)。異或運算的結果在二進制表示中,兩個數對應位相同則為 0,相異則為 1。
  • 如果結果小于 0,則說明這兩個數異號;如果結果大于 0,則說明這兩個數同號。
int a = 1;
int b = 2;
System.out.println(((a ^ b) < 0));  // false,a 和 b 同號int c = -1;
int d = 2;
System.out.println(((c ^ d) < 0));  // true,a 和 b 異號

2.4.取反運算 (~)

2.4.1.自增

int n = 2;
n = -~n;
System.out.println(n);	// 3

2.4.2.自減

int n = 2;
n = ~-n;
System.out.println(n);	// 1

2.5.移位運算 (<<、>>、>>>)

2.5.1.乘以 2

在二進制表示中,將一個數乘以 2 就等于將它向左移動 1 位,低位補 0。

int n = 3;
n <<= 1;
System.out.println(n);		// 6

2.5.2.除以 2

在二進制表示中,將一個數乘以 2 就等于將它向右移動 1 位,高位補符號位。

int n = 4;
n >>= 1;
System.out.println(n);		// 2

更多有關 Java 中移位運算符的細節可以參考 Java 基礎面試題——運算符這篇文章。

3.應用

大家可以去 LeetCode 上找相關的位運算的題目來練習,或者也可以直接查看 LeetCode 算法刷題目錄 (Java) 這篇文章中的位運算章節。如果大家發現文章中的錯誤之處,可在評論區中指出。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/168029.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/168029.shtml
英文地址,請注明出處:http://en.pswp.cn/news/168029.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

一起學docker系列之八使用 Docker 安裝配置 MySQL

目錄 前言步驟 1&#xff1a;拉取 MySQL 鏡像步驟 2&#xff1a;運行 MySQL 容器步驟 3&#xff1a;檢查容器狀態步驟 4&#xff1a;進入 MySQL 容器步驟 5&#xff1a;配置 MySQL 字符編碼步驟 6&#xff1a;重啟 MySQL 容器步驟 7&#xff1a;測試字符編碼步驟 8&#xff1a;…

防止應用程序截屏(容器式,防止極域電子教室和錄屏軟件錄制)

核心原理、實現目的 1、使用Panel容器將外部窗口嵌入自己寫的程序 2、使用防止截屏的函數來對窗口透明&#xff0c;這可以使本窗口內所有窗口在錄屏軟件上消失 3、解放&#xff0c;抓取&#xff0c;存儲句柄&#xff0c;實現擺脫錄屏&#xff08;極域監控&#xff09; 程序…

用 Addon 增強 Node.js 和 Electron 應用的原生能力

前言 Node.js Addon 是 Node.js 中為 JavaScript 環境提供 C/C 交互能力的機制。其形態十分類似 Java 的 JNI&#xff0c;都是通過提供一套 C/C SDK&#xff0c;用于在 C/C 中創建函數方法、進行數據轉換&#xff0c;以便 JavaScript / Java 等語言進行調用。這樣編寫的代碼通常…

Spring - Mybatis-設計模式總結

Mybatis-設計模式總結 1、Builder模式 2、工廠模式 3、單例模式 4、代理模式 5、組合模式 6、模板方法模式 7、適配器模式 8、裝飾者模式 9、迭代器模式 雖然我們都知道有26個設計模式&#xff0c;但是大多停留在概念層面&#xff0c;真實開發中很少遇到&#xff0c;…

【數據結構】時間和空間復雜度

馬上就要進入到數據結構的學習了 &#xff0c;我們先來了解一下時間和空間復雜度&#xff0c;這也可以判斷我們的算法是否好壞&#xff1b; 如何衡量一個算法的好壞&#xff1f; 就是看它的算法效率 算法效率 算法效率分析分為兩種&#xff1a;第一種是時間效率&#xff0c;第…

C++ Qt QVariant類型使用介紹與代碼演示

作者:令狐掌門 技術交流QQ群:675120140 csdn博客:https://mingshiqiang.blog.csdn.net/ 文章目錄 一、QVariant基本用法二、自定義類型使用QVariant三、其它用法賦值修改和替換值使用`QVariant::setValue()`設置值復制構造函數和賦值操作比較使用`QVariant::swap()`交換值使…

CVE-2023-22515:Atlassian Confluence權限提升漏洞復現 [附POC]

文章目錄 Atlassian Confluence權限提升(CVE-2023-22515)漏洞復現 [附POC]0x01 前言0x02 漏洞描述0x03 影響版本0x04 漏洞環境0x05 漏洞復現1.訪問漏洞環境2.構造POC3.復現 0x06 修復建議 Atlassian Confluence權限提升(CVE-2023-22515)漏洞復現 [附POC] 0x01 前言 免責聲明&…

vue中下載文件后無法打開的坑

今天在項目開發的時候臨時要添加個導出功能我就寫了一份請求加導出得代碼&#xff0c; 代碼&#xff1a; //導出按鈕放開exportDutySummarizing (dataRangeInfo) {const params {departmentName: dataRangeInfo.name,departmentQode: dataRangeInfo.qode}//拼接所需得urlcons…

UserRole

Qt::UserRole 是 Qt::ItemDataRole 枚舉中的一個成員&#xff0c;用于表示自定義數據角色&#xff08;Data Role&#xff09;的起始值。 在 Qt 中&#xff0c;Qt::ItemDataRole 枚舉用于標識項&#xff08;Item&#xff09;中不同類型的數據。這些數據角色包括 Qt::DisplayRol…

目標檢測YOLO系列從入門到精通技術詳解100篇-【目標檢測】紅外熱成像

目錄 前言 知識儲備 紅外熱成像儀基礎知識 算法原理 紅外熱成像探測距離 紅外圖像增強

第一百七十八回 介紹一個三方包組件:SlideSwitch

文章目錄 1. 概念介紹2. 使用方法3. 代碼與效果3.1 示例代碼3.2 運行效果 4. 內容總結 我們在上一章回中介紹了"如何創建垂直方向的Switch"相關的內容&#xff0c;本章回中將 介紹SlideSwitch組件.閑話休提&#xff0c;讓我們一起Talk Flutter吧。 1. 概念介紹 我們…

多功能智能燈桿主要功能有哪些?

多功能智能燈桿這個詞相信大家都不陌生&#xff0c;最近幾年多功能智能燈桿行業發展迅速&#xff0c;迅速取代了傳統路燈&#xff0c;那么多功能智能燈桿相比傳統照明路燈好在哪里呢&#xff0c;為什么大家都選擇使用叁仟智慧多功能智能燈桿呢&#xff1f;所謂多功能智能燈桿著…

【libGDX】Mesh紋理貼圖

1 前言 紋理貼圖的本質是將圖片的紋理坐標與模型的頂點坐標建立一一映射關系。紋理坐標的 x、y 軸正方向分別朝右和朝下&#xff0c;如下。 2 紋理貼圖 本節將使用 Mesh、ShaderProgram、Shader 實現紋理貼圖&#xff0c;OpenGL ES 的實現見博客 → 紋理貼圖。 DesktopLauncher…

超級應用平臺(HAP)起航

各位明道云用戶和伙伴&#xff0c; 今天&#xff0c;我們正式發布明道云10.0版本。從這個版本開始&#xff0c;我們將產品名稱正式命名為超級應用平臺&#xff08;Hyper Application Platform, 簡稱HAP&#xff09;。我們用“超級”二字表達產品在綜合能力方面的突破&#xff…

清華系下一代 LCM

LCM LoRA模型是一種創新的深度學習模型&#xff0c;它通過特殊的技術手段&#xff0c;顯著提高了圖像生成的效率。這種模型特別適用于需要快速生成高質量圖像的場景&#xff0c;如藝術創作、實時圖像處理等。 GitHub - luosiallen/latent-consistency-model: Latent Consistenc…

視頻監控中的智能算法與計算機視覺技術

智能視頻監控是一種基于人工智能技術的監控系統&#xff0c;它能夠通過對圖像和視頻數據進行分析&#xff0c;自動識別目標物體、判斷其行為以及進行異常檢測等功能&#xff0c;從而實現對場景的智能化監管。以下是常見的一些用于智能視頻監控的算法&#xff1a; 1、人臉識別技…

RabbitMQ簡易安裝

一般來說安裝 RabbitMQ 之前要安裝 Erlang &#xff0c;可以去Erlang官網下載。接著去RabbitMQ官網下載安裝包&#xff0c;之后解壓縮即可。 Erlang官方下載地址&#xff1a;Downloads - Erlang/OTP RabbitMQ官方下載地址&#xff1a;Downloading and Installing RabbitMQ —…

org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder

密碼&#xff0c;加密&#xff0c;解密 spring-security-crypto-5.7.3.jar /** Copyright 2002-2011 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with t…

Kafka(一)

一&#xff1a;簡介 解決高吞吐量項目的需求 是一款為大數據而生的消息中間件&#xff0c;具有百億級tps的吞吐量&#xff0c;在數據采集、傳輸、存儲的過程中發揮著作用 二&#xff1a;為什么要使用消息隊列 一個普通訪問量的接口和一個大并發的接口&#xff0c;它們背后的…

C/C++---------------LeetCode第1512. 好數對的數目

好數對的數目 題目及要求暴力算法哈希算法在main內使用 題目及要求 給你一個整數數組 nums 。 如果一組數字 (i,j) 滿足 nums[i] nums[j] 且 i < j &#xff0c;就可以認為這是一組 好數對 。 返回好數對的數目。 示例 1&#xff1a; 輸入&#xff1a;nums [1,2,3,1,…