【面试记录】1.给定一个由正数,负数和0组成的整数数组,将所有为0的元素,挪到数组末尾。2.给定任意一个自然数,获取它重新排列后,下一个比它大的自然数。(Leetcode 031 下一个排列)

 今天给各位分享前两天遇到的面试题,原题如下:

1.给定一个由正数,负数和0组成的整数数组,将所有为0的元素,挪到数组末尾。要求时间复杂度O(n)

        请设计一个函数,完成此功能。(语言不限)

2.给定任意一个自然数,获取它重新排列后,下一个比它大的自然数,要求时间复杂度O(n)。例如:
        给定1233,它的下一个是1323;
        给定1323,它的下一个是1332;
        给定9876,它的下一个不存在;

        请设计一个函数,完成此功能。(语言不限)

第一题很简单不多说,第二题是典型的字典序算法,有点意思。贴上代码,具体解题思路在注释里写的很详细了,还没懂的(说明你太笨了?)请在评论区留言。

import java.util.ArrayList;

public class exam
{
    public static void main(String[] args)
    {
        System.out.println("题目1:");
//        int[] ints = {0, 1, 3, 4, 0, -1, -5, 0, -3, 0, 2, 6, 9, 0};使用过的测试数据
        int[] ints = {9, 9, 0, 0, 9, 0, 0};
        ints = exam1(ints);
        for (int anInt : ints) {
            System.out.print(anInt + ",");
        }
        System.out.println();

        System.out.println("题目2:");
        int num = 1323;
        String result = exam2(num);
        System.out.println("数字 " + num + "比他大的排列为" + result);
    }

    /*给定一个由正数,负数和0组成的整数数组,将所有为0的元素,挪到数组末尾。
    要求时间复杂度O(n),请设计一个函数,完成此功能。(语言不限)*/
    static int[] exam1(int[] intArr)
    {
//        设置变量
        int i = 0;
        int j = intArr.length - 1;
//        循环遍历
        while (i < j) {
//            如果arr[j]为0,则j--并continue进行下一次循环
            if (intArr[j] == 0) {
                j--;
                continue;
            }
//            代码如果可以走到这里,则代表arr[j]不为0,那么就看arr[i]是否为0,是则调换位置,不是则i++查下一个。
//            循环直到i !< j
            if (intArr[i] == 0) {
//                这里调换因为题目给出的是定值,就不需要设置temp变量了
                intArr[i] = intArr[j];
                intArr[j] = 0;
                j--;
            }
            i++;
        }
        return intArr;
    }

    //    给定任意一个自然数,获取它重新排列后,下一个比它大的自然数,要求时间复杂度O(n)。例如:
//    给定1233,它的下一个是1323;
//    给定1323,它的下一个是1332;
//    给定9876,它的下一个不存在;
//    请设计一个函数,完成此功能。(语言不限)
    static String exam2(int num)
    {
//        创建空数组
        ArrayList<Integer> nums = new ArrayList<>();
//        分解自然数并放入数组
        while ((num % 10) > 0) {
            int tmp = num % 10;
            num = num / 10;
            nums.add(0, tmp);
        }
//        为了和原数接近,我们需要尽量保持高位不变,低位在最小的范围内变换顺序。

//        0.从后向前查看逆序区域,找到逆序区域的前一位,也就是数字置换的边界
        int criticalPoint = findCriticalPoint(nums);
//        1.首先检查是否为最大值
        if (criticalPoint == -1) {
            return "不存在";
        }
//        2.把逆序区域的前一位和逆序区域中刚刚大于它的数字交换位置并把原来的逆序区域转为顺序
        return reorder(nums, criticalPoint).toString();
    }

    static int findCriticalPoint(ArrayList<Integer> nums)
    {
        for (int i = nums.size() - 1; i > 0; i--) {
            if (nums.get(i) > nums.get(i - 1)) {
//                如果找到临界值,返回那个值
                return i;
            }
        }
//        没找到,代表该数组每个数都比后面的数大也就是逆序排列
        return -1;
    }

    static ArrayList<Integer> reorder(ArrayList<Integer> nums, int index)
    {
        int left = nums.get(index - 1);
        for (int i = nums.size() - 1; i >= index; i--) {
            int right = nums.get(i);
            if (left < right) {
                nums.set(index - 1, right);
                nums.set(i, left);
                break;
            }
        }
        for (int i = index, j = nums.size() - 1; i < j; i++, j--) {
            int temp = nums.get(i);
            nums.set(i, nums.get(j));
            nums.set(j, temp);
        }
        return nums;
    }

}

 

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值