分治法的应用

超过一半的数

package 分治法;

/**
 * @author: DreamCode
 * @file: 超过一半以上的数.java
 * @time: 2022年2月27日-下午4:40:11
 * @思路: 
 */
public class 超过一半的数 {
	/*
	 * 数组中有一个数字出现的次数等于数组长度的一半,找出这个数字。
	 * */
	public static void main(String[] args) {
		int[] arr= {1,5,2,5,3,5,5,4};
		int candidate = arr[0];
		int nTimes=0;
		int countLastNum=0; //统计最后一个元素出现的次数;
		for(int i=0;i<arr.length;i++) {
			if(arr[i]==arr[arr.length-1]) {
				countLastNum++;
			}
			if(arr[i]!=candidate) {
				if(nTimes==0) {
					candidate=arr[i];
					nTimes=0;
					continue;
				}else {
					nTimes--;
				}
			}else {
				nTimes++;
			}
		}
		if(countLastNum==2/arr.length) {
			System.out.println(arr[arr.length-1]);
		}else {
			System.out.println(candidate);
		}

	}

}

超过一半以上的数

package 分治法;

/**
 * @author: DreamCode
 * @file: 超过一半以上的的数.java
 * @time: 2022年2月27日-下午4:31:46
 * @思路: 
 */
public class 超过一半以上的数 {

	public static void main(String[] args) {
		int[] arr = {5,5,5,5,1,2,3};
		int ans = more_half_num(arr);
		System.out.println(ans);
	}

	private static int more_half_num(int[] arr) {
		int l=1;
		int r=arr.length-1;
		int povit=0;
		while(l<=r) {
			while(l<=r&&arr[l]<=arr[povit])l++;
			while(l<=r&&arr[r]>=arr[povit])r--;
			if(l<r) {
				int temp = arr[l];
				arr[l]=arr[r];
				arr[r]=temp;
			}
		}
		int temp=arr[r];
		arr[r]=arr[povit];
		arr[povit]=temp;
		return arr[arr.length/2];
	}

}

快速排序

package 分治法;

/**
 * @author: DreamCode
 * @file: 最快速率_乱序数组中查找第k位.java
 * @time: 2022年2月27日-下午3:00:27
 * @思路: 快速排序的双指针思想,每一轮必定确定中间的数
 */
public class 最快速率_乱序数组中查找第k位 {

	public static void main(String[] args) {
		int[] arr = { 13, 12, 15, 17, 11, 19, 18, 14 };
		//11 12 13 14 15 17 18 19
		int k = 3;
		int ans = select_K(arr, 0, arr.length - 1, k);
		System.out.println(ans);
	}

	private static int select_K(int[] arr, int l, int r, int k) {
		int p = partition(arr, l, r); // 中位数所在的下标
		int p_K = p - l + 1; // 中位数所在的位置
		if (p_K == k)
			return arr[p];
		else if (p_K > k) {
			return select_K(arr, l, p - 1, k);
		} else {
			return select_K(arr, p + 1, r, k - p_K);
		}
	}

	private static int partition(int[] arr, int l, int r) {
		
		int midValueIndex = get_mid_index(arr,l,r);
		int temp = arr[l];
		arr[l] = arr[midValueIndex];
		arr[midValueIndex] = temp;
		int p = l + 1;
		int q = r;
		while (p <= q) {
			while (p <= q && arr[p] <= arr[l])
				p++;
			while (p <= q && arr[q] >= arr[l])
				q--;
			if (p < q) {
				int temp2 = arr[p];
				arr[p] = arr[q];
				arr[q] = temp2;
			}
		}
		temp = arr[l];
		arr[l] = arr[q];
		arr[q] = temp;
		return q;
	}

	private static int get_mid_index(int[] arr, int l, int r) {
		int midIndex = l + ((r - l) >> 1);
		int max = Math.max(arr[l], arr[midIndex]);
		max = Math.max(max, arr[r]);
		int min = Math.min(arr[l], arr[midIndex]);
		min = Math.min(min, arr[r]);
		int midValue = arr[l]+arr[r]+arr[midIndex]-min-max;
		return midValue==arr[l]?l:midValue==arr[r]?r:midIndex;
	}

}

最快速率_乱序数组中查找第k位

package 分治法;

/**
 * @author: DreamCode
 * @file: 最快速率_乱序数组中查找第k位.java
 * @time: 2022年2月27日-下午3:00:27
 * @思路: 快速排序的双指针思想,每一轮必定确定中间的数
 */
public class 最快速率_乱序数组中查找第k位 {

	public static void main(String[] args) {
		int[] arr = { 13, 12, 15, 17, 11, 19, 18, 14 };
		//11 12 13 14 15 17 18 19
		int k = 3;
		int ans = select_K(arr, 0, arr.length - 1, k);
		System.out.println(ans);
	}

	private static int select_K(int[] arr, int l, int r, int k) {
		int p = partition(arr, l, r); // 中位数所在的下标
		int p_K = p - l + 1; // 中位数所在的位置
		if (p_K == k)
			return arr[p];
		else if (p_K > k) {
			return select_K(arr, l, p - 1, k);
		} else {
			return select_K(arr, p + 1, r, k - p_K);
		}
	}

	private static int partition(int[] arr, int l, int r) {
		
		int midValueIndex = get_mid_index(arr,l,r);
		int temp = arr[l];
		arr[l] = arr[midValueIndex];
		arr[midValueIndex] = temp;
		int p = l + 1;
		int q = r;
		while (p <= q) {
			while (p <= q && arr[p] <= arr[l])
				p++;
			while (p <= q && arr[q] >= arr[l])
				q--;
			if (p < q) {
				int temp2 = arr[p];
				arr[p] = arr[q];
				arr[q] = temp2;
			}
		}
		temp = arr[l];
		arr[l] = arr[q];
		arr[q] = temp;
		return q;
	}

	private static int get_mid_index(int[] arr, int l, int r) {
		int midIndex = l + ((r - l) >> 1);
		int max = Math.max(arr[l], arr[midIndex]);
		max = Math.max(max, arr[r]);
		int min = Math.min(arr[l], arr[midIndex]);
		min = Math.min(min, arr[r]);
		int midValue = arr[l]+arr[r]+arr[midIndex]-min-max;
		return midValue==arr[l]?l:midValue==arr[r]?r:midIndex;
	}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

梦码城

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

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

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

打赏作者

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

抵扣说明:

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

余额充值