java 算法问题,高手请进!

reyoreyoreyo 2017-12-16 08:03:09
现在有一个 List<Integer> list 这个list数字不重复且已按从小到大排好序。

算法要求:最快找出这个list不连续的index位置的数字。(list必须是从1开始,连续的增量为1)
如:

List<Integer> list = Arrays.asList(2, 4, 6, 8, 9);返回0(如果不是从0开始返回0)
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);如果全部连续且返回list的最大值5

List<Integer> list = Arrays.asList(1, 2, 3, 4, 7); 返回4
List<Integer> list = Arrays.asList(1, 2, 6, 8, 9);返回2
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 8, 9, 12, 45, 200, 456);返回6

现在问题来了,如果这个list的几个万个数据,我们除了用
for (int i = 1; i < list.size; i++) {
}
来一个一个的对比,还有其它更快的方式,在第一时间找到第一个不连续的数字?
...全文
676 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
reyoreyoreyo 2017-12-18
  • 打赏
  • 举报
回复
引用 11 楼 still_rain 的回复:
[quote=引用 10 楼 hjgzj 的回复:] 后一位减前一位>1 就不连续了。注意数组越界
前后都是连续的,中间偶有不连续的数,例如:1,2,5,6,7,8,9,那样判断就不行的。[/quote]如果数字没有按小到大的顺序排好?有什么好的方法实现?下面的方法是有bug的,我只是提供了一个思路。你有高见或能找出bug不?
	public static int getSeriesMinNoSort(List<Integer> list) {
		int max = Collections.max(list);
		if (list.get(0) != 1) {
			return 0;
		}
		for (int i = 0; i < list.size(); i++) {
			if (Math.abs(list.get(i)) - 1 < list.size()) {
				list.set(Math.abs(list.get(i)) - 1, -list.get(Math.abs(list.get(i)) - 1));
			}
		}
		for (int i = 0; i < list.size(); i++) {
			if (list.get(i) > 0) {
				return i;
			}
		}
		return max;
	}
爱摸鱼de老邪 2017-12-18
  • 打赏
  • 举报
回复
引用 10 楼 hjgzj 的回复:
后一位减前一位>1 就不连续了。注意数组越界
前后都是连续的,中间偶有不连续的数,例如:1,2,5,6,7,8,9,那样判断就不行的。
  • 打赏
  • 举报
回复
后一位减前一位>1 就不连续了。注意数组越界
Inhibitory 2017-12-17
  • 打赏
  • 举报
回复
引用 6 楼 reyoreyoreyo 的回复:
之前还有一个高人提到一种方法。但没有人具体写出来,希望有高人能表达出来!!! 直接用二进制操作,比排序和遍历都快多了! 比较犀利的方法:凑m,m=4k-1,并且是4k-1>=n的最大整数(比如n=7,则m=7;n=16,则m=19;n=21,m=23以此类推) 那么只需要A[1]^A[2]^……^A[n-1]^A[n]^{A[m-2]^A[m-1]^A[m]},即可 原因:从4的整数倍开始,连续4个数字异或,结果为(例如4^5^6^7的结果是0;204^205^206 = 207;8^10^11=9) 所以0^1^2^……^m的结果为0,却哪个数字,则A[1]^A[2]^……^A[n-1]^A[n]^{A[m-2]^A[m-1]^A[m]}的结果就是所缺的数字
二进制的时间复杂度是 O(N),二分搜索是 O(lgN)
reyoreyoreyo 2017-12-17
  • 打赏
  • 举报
回复
之前还有一个高人提到一种方法。但没有人具体写出来,希望有高人能表达出来!!! 直接用二进制操作,比排序和遍历都快多了! 比较犀利的方法:凑m,m=4k-1,并且是4k-1>=n的最大整数(比如n=7,则m=7;n=16,则m=19;n=21,m=23以此类推) 那么只需要A[1]^A[2]^……^A[n-1]^A[n]^{A[m-2]^A[m-1]^A[m]},即可 原因:从4的整数倍开始,连续4个数字异或,结果为(例如4^5^6^7的结果是0;204^205^206 = 207;8^10^11=9) 所以0^1^2^……^m的结果为0,却哪个数字,则A[1]^A[2]^……^A[n-1]^A[n]^{A[m-2]^A[m-1]^A[m]}的结果就是所缺的数字
reyoreyoreyo 2017-12-17
  • 打赏
  • 举报
回复
	public static int test(List<Integer> list) {

		int thisSize = list.size();
		if (thisSize == 0)
			return 0;

		int max = Collections.max(list);
		int mid = thisSize / 2;
		if (list.get(mid) - list.get(mid - 1) != 1)
			return list.get(mid - 1);

		int start = 0;
		int end = thisSize - 1;
		while (start <= end) {
			mid = (end - start) / 2 + start;
			if (? < list.get(mid)) {
				end = mid - 1;
			} else if (? > list.get(mid)) {
				start = mid + 1;
			} else {
				return list.get(mid);
			}
		}
		return max;
	}
?问号的地方应该怎么表达?
reyoreyoreyo 2017-12-17
  • 打赏
  • 举报
回复
引用 3 楼 still_rain 的回复:
怎么可能一样,二分查找平均时间复杂度是O(logN),最坏的情况下才是O(N)。
你写一个?
爱摸鱼de老邪 2017-12-17
  • 打赏
  • 举报
回复

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;


public class Test{
	public static void main(String[] args){
		List<Integer> list1 = Arrays.asList(2, 4, 6, 8, 9);
		List<Integer> list2 = Arrays.asList(1, 2, 3, 4, 5);//如果全部连续且返回list的最大值5
		List<Integer> list3 = Arrays.asList(1, 2, 3, 4, 7); //返回4
		List<Integer> list4 = Arrays.asList(1, 2, 6, 8, 9);//返回2
		List<Integer> list5 = Arrays.asList(1, 2, 3, 4, 5, 6, 8, 9, 12, 45, 200, 456);//返回6
		System.out.println(find_breakpoint(list1));
		System.out.println(find_breakpoint(list2));
		System.out.println(find_breakpoint(list3));
		System.out.println(find_breakpoint(list4));
		System.out.println(find_breakpoint(list5));
		
	}
	
	public static int find_breakpoint(List<Integer> li)
	{
		if(li.size()==0)
			return -1;
		else
		{
			int start=0;
			int end=li.size()-1;
			if(li.get(start)!=1)
				return 0;
			else if((end+1)==li.get(end))
				return li.get(end);
			else
			{	
				int mid=0;
				while(start<=end)
				{
					mid=(start+end)/2;
					if((mid+1)==li.get(mid))
					{
						if((mid+2)<li.get(mid+1))
							return li.get(mid);
						start=mid+1;
					}
					else if((mid+1)<li.get(mid))
					{
						if((mid)==li.get(mid-1))
							return li.get(mid);
						end=mid-1;
					}
				}
				return -1;
			}
		}
	}
}

结果: 0 5 4 6 6
reyoreyoreyo 2017-12-17
  • 打赏
  • 举报
回复
引用 7 楼 Inhibitory 的回复:
[quote=引用 6 楼 reyoreyoreyo 的回复:] 之前还有一个高人提到一种方法。但没有人具体写出来,希望有高人能表达出来!!! 直接用二进制操作,比排序和遍历都快多了! 比较犀利的方法:凑m,m=4k-1,并且是4k-1>=n的最大整数(比如n=7,则m=7;n=16,则m=19;n=21,m=23以此类推) 那么只需要A[1]^A[2]^……^A[n-1]^A[n]^{A[m-2]^A[m-1]^A[m]},即可 原因:从4的整数倍开始,连续4个数字异或,结果为(例如4^5^6^7的结果是0;204^205^206 = 207;8^10^11=9) 所以0^1^2^……^m的结果为0,却哪个数字,则A[1]^A[2]^……^A[n-1]^A[n]^{A[m-2]^A[m-1]^A[m]}的结果就是所缺的数字
二进制的时间复杂度是 O(N),二分搜索是 O(lgN)[/quote] 能帮忙改写一下二分搜索不?
public static int test(List<Integer> list) {
 
    int thisSize = list.size();
    if (thisSize == 0)
        return 0;
 
    int max = Collections.max(list);
    int mid = thisSize / 2;
    if (list.get(mid) - list.get(mid - 1) != 1)
        return list.get(mid - 1);
 
    int start = 0;
    int end = thisSize - 1;
    while (start <= end) {
       //这里要怎么表达?
        mid = (end - start) / 2 + start;
        if (? < list.get(mid)) {
            end = mid - 1;
        } else if (? > list.get(mid)) {
            start = mid + 1;
        } else {
            return list.get(mid);
        }
    }
    return max;
}
reyoreyoreyo 2017-12-16
  • 打赏
  • 举报
回复
引用 1 楼 Inhibitory 的回复:
可以试试二分查找的思想, mid = (low+high)/2 如果是连续的,则 list[mid] 是期望的值(可以计算出来的),那么继续二分搜索 [mid, high] 部分 如果不连续的,则 list[mid] 不是期望的值,二分搜索 [low, mid] 部分
那和for的效率不是一样?
for (int i = 1; i < thisSize; i++) {
				if (list.get(i) - list.get(i - 1) != 1) {
					return list.get(i - 1);
				}
			}
爱摸鱼de老邪 2017-12-16
  • 打赏
  • 举报
回复
怎么可能一样,二分查找平均时间复杂度是O(logN),最坏的情况下才是O(N)。
Inhibitory 2017-12-16
  • 打赏
  • 举报
回复
可以试试二分查找的思想, mid = (low+high)/2 如果是连续的,则 list[mid] 是期望的值(可以计算出来的),那么继续二分搜索 [mid, high] 部分 如果不连续的,则 list[mid] 不是期望的值,二分搜索 [low, mid] 部分

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧