常见基本排序、二分法与异或运算

目录

一、常见基本排序

选择排序​编辑

冒泡排序​编辑

插入排序

二、二分法

在一个有序数组中,找某个数是否存在

在一个有序数组中,找>=某个数最左侧的位置

在一个有序数组中,找<=某个数最右侧的位置

相邻两数不等,局部最小值问题

三、异或运算

不用额外变量交换两个数

一个数组中有一种数出现奇数次,其他数都出现了偶数次,怎么找到并打印这种数

一个数组中有两种数出现奇数次,其他数都出现了偶数次,怎么找到并打印这两种数

数出二进制1的个数


一、常见基本排序

选择排序
在这里插入图片描述

基本思路:从第一位开始标记,每次选出最小数字与标记位交换

代码实现:

	private static void selectSort(int[] arr) {
		if(arr == null || arr.length < 2){
			return;
		}
		for (int i = 0; i < arr.length-1; i++) {
			int index = i;
			for (int j = i + 1; j < arr.length; j++) {
				if(arr[j] < arr[index]){
					index = j;
				}
			}
			swap(arr, i ,index);
		}
	}

冒泡排序
在这里插入图片描述

基本思路:每次比较相邻两个数大小,每次循环选出当轮最大/小数字,每次循环次数环比减一

代码实现:

	private static void bubbleSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}
		for (int end = arr.length-1; end >0; end--) {
			for (int start = 0; start < end; start++) {
				if(arr[start]>arr[start+1]){
					swap(arr, start, start+1);
				}
			}
		}
	}

插入排序

基本思路:保证前面有序的情况下,依次把后面数字插入到指定位置继续保证有序

代码实现:

	private static void insertionSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}
		for (int i = 1; i < arr.length; i++) {
			for (int j = i; j > 0 && arr[j]<arr[j-1]; j--) {
				swap(arr,j,j-1);
			}
		}
	}

二、二分法

基本思路:根据左右边界计算中间位置,中间值和目标值比较,如果中间值小于目标值,左边界等于中间位置+1,如果中间值大于目标值,右边界等于中间位置-1。

在一个有序数组中,找某个数是否存在

    private static boolean isExist(int[] arr, int num) {
		if(arr == null || arr.length <2){
			return false;
		}
		int L = 0;
		int R = arr.length-1;
		int mid = 0;
		while (L < R){
			mid = L + ((R-L) >> 1);
			if(arr[mid] == num){
				return true;
			}else if(arr[mid] < num){
				L = mid + 1;
			}else{
				R = mid - 1;
			}
		}
		return arr[L] == num;
	}

在一个有序数组中,找>=某个数最左侧的位置

	private static int leftmostPosition(int[] arr, int num) {
		int L = 0;
		int R = arr.length-1;
		int mid = 0;
		int index = -1;
		while (L <= R){
			mid = L + ((R-L) >> 1);
			if(arr[mid] >= num){
				index = mid;
				R = mid - 1;
			}else{
				L = mid + 1;
			}
		}
		return index;
	}

在一个有序数组中,找<=某个数最右侧的位置

	private static int rightmostPosition(int[] arr, int num) {
		int L = 0;
		int R = arr.length-1;
		int mid = 0;
		int index = -1;
		while (L <= R){
			mid = L + ((R-L) >> 1);
			if(arr[mid] <= num){
				index = mid;
				L = mid + 1;
			}else{
				R = mid - 1;
			}
		}
		return index;
	}

相邻两数不等,局部最小值问题

    private static int localMinimum(int[] arr){
		if(arr == null || arr.length<=1){
			return -1;
		}
		if(arr[0] < arr[1]){
			return 0;
		}
		if(arr[arr.length - 1] < arr[arr.length - 2]){
			return arr.length - 1;
		}
		int L = 1;
		int R = arr.length - 2;
		int mid = 0;
		while (L < R){
			mid = L + ((R - L) >> 1);
			if(arr[mid] > arr[mid-1]){
				R = mid - 1;
			}else if(arr[mid] > arr[mid+1]){
				L = mid + 1;
			}else{
				return mid;
			}
		}
		return -1;
	}

三、异或运算

基本规则:相同则0,不同则1

不用额外变量交换两个数

	private static void swap(int[] arr, int a, int b){
		arr[a] = arr[a] ^ arr[b];
		arr[b] = arr[a] ^ arr[b];
		arr[a] = arr[a] ^ arr[b];
	}

一个数组中有一种数出现奇数次,其他数都出现了偶数次,怎么找到并打印这种数

	private static int getNum(int[] arr){
		if(arr == null || 0 == arr.length){
			return -1;
		}
		int num = 0;
		for (int i = 0; i < arr.length; i++) {
			num ^= arr[i];
		}
		return num;
	}

一个数组中有两种数出现奇数次,其他数都出现了偶数次,怎么找到并打印这两种数

    private static void printNums(int[] arr){
		int num = 0;
		for (int i = 0; i < arr.length; i++) {
			num ^= arr[i]; // 最终结果是两种数:a^b
		}
		// a^b不等于0,所以在某个位置,一个数是0,一个数是1
		// 找出最右位置的1,然后取该位置为0的数字进行异或就可以找出其中一个数
		int farRightOne = num & ((~num)+1);

		int onlyOne = 0;
		for (int i = 0; i < arr.length; i++) {
			if((arr[i] & farRightOne) != 0){
				onlyOne ^= arr[i];
			}
		}
		System.out.println(onlyOne + " ^ " + (num ^ onlyOne));
	}

数出二进制1的个数

    private static int getNumberOfOne(int num) {
        int count = 0;
        while (num != 0 ){
             // 方法1:每次取出最右边的进行异或
             //int farRightOne = num & ((~num)+1); 
             //num ^= farRightOne;
             
             // 方法2:与运算
             num &= num  - 1;

             count++;
        }
        return count;
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员Forlan

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值