找出给定无序数组中未出现的最小正整数

找出给定无序数组中未出现的最小正整数

时间复杂度O(n),空间复杂度O(1)

例如:

arr=[-1,2,3,4]。返回1。

arr=[1,2,3,4]。返回5。


public void test2() {
    System.out.println(funcFinal(new int[]{-1,5,1,6,2}));
    System.out.println(funcFinal(new int[]{3,2,1,5,4}));
}/* out:
 * 原数组:[-1, 5, 1, 6, 2]
 * 处理后:[1, 2, 1, 6, 2]
 * 结果:3
 * 原数组:[3, 2, 1, 5, 4]
 * 处理后:[1, 2, 3, 4, 5]
 * 结果:6
 */
    
public int funcFinal(int[] arr) {
    System.out.println("原数组:" + Arrays.toString(arr));
    /* 
     * right是一个边界值,表示用数组中元素组成的从1开始的连续整数序列中可能的最大值(初始等于数组长度)。
     * 处理数组过程中如果遇到比right大的数,就表示该数不合法,应该被丢掉(代码中还处理了其它表示数不合法的情况)。
     * >> 随着数组元素被处理,每遇到一个不合法的元素,就应将right减1。
     */
    int right = arr.length;
    /*
     * 索引left(初始为0),left将数组分成两部分。
     * [0,left)是处理完成的部分,其中每个元素都满足a[i]=i+1;
     * [left,right]是待处理部分。
     * >> 随着数组元素被处理,left会逐渐向右移动。
     */
    int left = 0; 
    
    while (left + 1 <= right) { // 正在处理的元素的值(left+1) <= 边界值
        // 分支1、arr[left]在理想的位置
        // 则处理完成部分长度加1,然后继续处理未完成部分的下一个待处理元素
        if (arr[left] == left + 1) { 
            left++; 
        } 
        // 分支2、arr[left]是不合法的数据
        // 则先将right减1,然后丢掉不合法的数并将待处理部分最后一个元素填充到left位置继续处理
        else if (arr[left] < left + 1 || arr[left] > right) {
            right--;
            arr[left] = arr[right];
        } 
        // 分支3、arr[left]合法,但是没有在理想的位置上
        // 则需要交换arr[left]与其理想位置上元素,然后继续处理交换后left位置处的元素
        // 求理想位置p的索引:p+1 = arr[left] >> p = arr[left]-1
        else { 
            // 如果要交换的两个元素相同,也算当前处理的元素arr[left]不合法,进行与分支2一样的处理
            if(arr[left] == arr[arr[left] - 1]) {
                right--;
                arr[left] = arr[right];
            } else {
                swap(arr, left, arr[left] - 1);
            }
        }
    }
    System.out.println("处理后:" + Arrays.toString(arr));
    return left + 1;
}
private void swap(int[] a, int i, int j) {
    int temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值