導學
藍橋杯課程安排:
參考書籍:
學習方法:
位運算
1-1000這1000個數放在含有1001個元素的數組中,只有唯一的一個元素值重復,其它均只出現一次。
每個數組元素只能訪問一次,設計一個算法,將它找出來;不用輔助存儲空間,能否設計一個算法實現?
1 package 算法基礎; 2 import 算法基礎.數組隨機排序; 3 import java.util.Random; 4 5 /** 6 * @Auther:zhushen 7 * @Date:2021/1/13 8 * @Description:位運算 9 * @version:1.0 10 */ 11 public class 唯一成對的數 { 12 /* 13 1-1000這1000個數放在含有1001個元素的數組中,只有唯一的一個元素值重復,其它均只出現一次。 14 每個數組元素只能訪問一次,設計一個算法,將它找出來;不用輔助存儲空間,能否設計一個算法實現? 15 */ 16 public static void main(String[]args){ 17 System.out.println("============方法一============"); 18 //不使用輔助存儲空間 19 //思路:將數組元素與正常無重復數組元素進行異或(數組元素為0—10中的整數)
//異或 20 //代碼實現參考:兩個數交換值 21 //num1 = num1^num2; 22 //num2 = num1^num2; 23 //num1 = num1^num2; 24 int N = 11; 25 int[]arr = new int[N]; 26 //填充整數 27 for (int i =0;i<arr.length-1;i++){ 28 arr[i]=i+1; 29 } 30 //最后一個數,是隨機數 31 arr[arr.length-1]= new Random().nextInt(N-1)+1; 32 //隨機下標 33 數組隨機排序.shuffle(arr); 34 int x1 = 0; 35 for(int i = 1;i<=N-1;i++){ 36 x1 = (x1^i); 37 } 38 for(int i = 0;i<N;i++){ 39 x1 = x1^arr[i]; 40 } 41 for (int value : arr) { 42 System.out.print(value); 43 } 44 System.out.println("\n"+x1); 45 46 System.out.println("============方法二============"); 47 //使用輔助存儲空間 48 //思路:使用數組下標查出重復元素 49 //代碼實現:使用輔助存儲空間,將該數組的值作為輔助存儲空間(數組)的下標。 50 int[]helper = new int[N]; 51 for (int i=0;i<N;i++){ 52 helper[arr[i]]++;//上一個數組的值作為該數組元素的下標 53 } 54 for (int i=0;i<N;i++){ 55 if(helper[i]==2){ 56 System.out.println(i); 57 break; 58 } 59 } 60 } 61 }
1 package 算法基礎; 2 import java.util.Random; 3 4 /** 5 * @Auther:zhushen 6 * @Date:2021/1/13 7 * @Description:tools 8 * @version:1.0 9 */ 10 public class 數組隨機排序 { 11 12 13 /** 14 * 隨機排序 15 */ 16 17 private static Random rand = new Random(); 18 19 public static void swap(int[] a, int i, int j) { 20 int temp = a[i]; 21 a[i] = a[j]; 22 a[j] = temp; 23 } 24 25 public static void shuffle(int[] arr) { 26 int length = arr.length; 27 for (int i = length; i > 0; i--) { 28 int randInd = rand.nextInt(i); 29 swap(arr, randInd, i - 1); 30 } 31 } 32 }
一個數組里除了某一個數字之外,其他的數字都出現了兩次。請寫程序找出這個只出現一次的數字。
1 package 算法基礎; 2 3 import java.util.Random; 4 5 /** 6 * @Auther:zhushen 7 * @Date:2021/1/13 8 * @Description:位運算 9 * @version:1.0 10 */ 11 public class 找出落單的數 { 12 public static void main(String[] args) { 13 System.out.println("============方法一============"); 14 //不使用輔助存儲空間 15 //思路:直接異或,A^A=0、A^0=A 16 //代碼實現參考:兩個數交換值 17 //num1 = num1^num2; 18 //num2 = num1^num2; 19 //num1 = num1^num2; 20 int N = 11; 21 int[]arr = new int[N]; 22 //填充整數 23 for (int i =0;i<arr.length-1;i=i+2){ 24 arr[i+1]=arr[i]=i+1; 25 } 26 //最后一個數,是隨機數 27 arr[arr.length-1]= new Random().nextInt(N-1)+1; 28 //隨機下標 29 數組隨機排序.shuffle(arr); 30 int x1 = 0; 31 for(int i = 0;i<N;i++){ 32 x1 = x1^arr[i]; 33 } 34 for (int value : arr) { 35 System.out.print(value); 36 } 37 System.out.println("\n"+x1); 38 39 System.out.println("============方法二============"); 40 //使用輔助存儲空間 41 //思路:使用數組下標查出不重復元素 42 //代碼實現:使用輔助存儲空間,將該數組的值作為輔助存儲空間(數組)的下標。 43 int[]helper = new int[N]; 44 for (int i=0;i<N;i++){ 45 helper[arr[i]]++;//上一個數組的值作為該數組元素的下標 46 } 47 for (int i=0;i<N;i++){ 48 if(helper[i]==1){ 49 System.out.println(i); 50 break; 51 } 52 } 53 } 54 }
請實現一個函數,輸入一個整數,輸出該數二進制表示中1的個數。
例:9的二進制表示為1001,有2位是1
1 package 算法基礎; 2 3 import java.util.Scanner; 4 5 /** 6 * @Auther:zhushen 7 * @Date:2021/1/13 8 * @Description:位運算 9 * @version:1.0 10 */ 11 public class 二進制中1的個數 { 12 public static void main(String[] args) { 13 System.out.println("請輸入要求的數:"); 14 Scanner sc = new Scanner(System.in); 15 int N = sc.nextInt(); 16 System.out.println(Integer.toString(N, 2)); 17 //方法一: 18 //拿1從右向左與原數字做&運算 19 int count = 0; 20 //對比每一位 21 for (int i = 0; i < 32; i++) { 22 if ((N & (1 << i)) == (1 << i)) { 23 count++; 24 } 25 } 26 System.out.println(count); 27 28 //方法二:把原數字往右移與1做&運算 29 count = 0; 30 for(int i = 0;i<32;i++){ 31 if(((N>>>i)&1)==1) 32 count++; 33 } 34 System.out.println(count); 35 36 //方法三:原數字-1,每次可消除一個1,然后原數字與-1后的數字做與運算。 37 //現象(1):1000-1=0111 38 //現象(2):1000&0111=0000 39 count = 0; 40 while(N!=0){ 41 N = ((N-1)&N); 42 count++; 43 } 44 System.out.println(count); 45 } 46 }
用一條語句判斷一個整數是不是2的整數次方。
1 int N = 18; 2 System.out.println(Integer.toString(N, 2)); 3 if(((N-1)&N)==0){ 4 System.out.println("是"); 6 }else{ 7 System.out.println("不是"); 8 }
1 package 算法基礎; 2 3 import org.junit.Assert; 4 5 /** 6 * @Auther:zhushen 7 * @Date:2021/2/5 8 * @Description:位運算,見一個記一個。 9 * @version:1.0 10 */ 11 public class 整數的奇偶位互換 { 12 public static void main(String[] args) { 13 int a = 0b01000000_00000000_00000000_00000000; 14 int b =m(a); 15 Assert.assertEquals(b,0b10000000_00000000_00000000_00000000); 16 } 17 private static int m(int i){ 18 int ou = i&0xaaaaaaaa;//原數字和1010 1010 1010....(偶數位為1,奇數位為0)做與運算取出偶數位 19 int ji = i&0x55555555;//原數字和0101 0101 0101....(偶數位為0,奇數位為1)做與運算取出奇數位 20 return (ou>>1)^(ji<<1);//連起來 21 } 22 }
(1)給定一個介於0和1之間的實數,(如0.625),類型為double,打印它的二進制表示(0.101,因為小數點后的二進制分別表示0.5,0.25.0.125......)。
(2)如果該數字無法精確地用32位以內的二進制表示,則打印“ERROR"
1 package 算法基礎; 2 3 import com.sun.org.apache.bcel.internal.generic.RETURN; 4 5 /** 6 * @Auther:zhushen 7 * @Date:2021/2/5 8 * @Description:位運算,見一個記一個 9 * @version:1.0 10 */ 11 public class 二進制表示浮點實數 { 12 public static void main(String[] args) { 13 double num = 0.625; 14 StringBuilder sb = new StringBuilder("0."); 15 while(num>0){ 16 //乘2挪整 17 double r = num*2; 18 //判斷整數部分 19 if(r>=1){ 20 sb.append("1"); 21 //消除整數部分 22 num=r-1; 23 }else{ 24 sb.append("0"); 25 num = r; 26 } 27 if(sb.length()>34){ 28 System.out.println("ERROR"); 29 return; 30 } 31 } 32 System.out.println(sb.toString()); 33 } 34 }
1 package 算法基礎; 2 3 /** 4 * @Auther:zhushen 5 * @Date:2021/2/6 6 * @Description: 7 * @version:1.0 8 */ 9 public class 出現k次與1次 { 10 public static void main(String[] args) { 11 int[]arr = {2,2,2,9,7,7,7,3,3,3,6,6,6,0,0,0}; 12 int len = arr.length; 13 char[][]kRadix = new char[len][]; 14 int k = 3; 15 //轉成k進制字符數組 16 int maxLen = 0; 17 for(int i=0;i<len;i++){ 18 //求每個數字的三進制字符串並翻轉,然后轉為字符數組 19 kRadix[i] = new StringBuffer(Integer.toString(arr[i],k)).reverse().toString().toCharArray(); 20 if(kRadix[i].length>maxLen){ 21 maxLen = kRadix[i].length; 22 } 23 } 24 int[] resArr = new int[maxLen]; 25 for(int i =0;i<len;i++){ 26 //不進位加法 27 for(int j = 0;j<maxLen;j++){ 28 if(j>=kRadix[i].length){ 29 resArr[j]+=0; 30 }else{ 31 resArr[j] +=(kRadix[i][j]-'0'); 32 } 33 } 34 35 36 } 37 int res = 0; 38 for(int i = 0;i<maxLen;i++){ 39 res+=(resArr[i]%k)*(int)(Math.pow(k,i));//8%3=2 40 } 41 System.out.println(res); 42 } 43 }