给定一个含不同整数的集合,返回其所有的子集,打败了92%

该算法有很多种解法,无外乎dfs bfs 递归与不递归,其实都差不多,我测了下运行速度也差不多,感觉lintcode 的提交有bug 每次提交运行速度不一样,我这套最开始运行250ms 后面又提交了次 跑了232ms
我主要加上了 快速排序 和二分查找 来降低排序和循环的次数 比参考答案快了几十ms

描述
中文
English
给定一个含不同整数的集合,返回其所有的子集。

子集中的元素排列必须是非降序的,解集必须不包含重复的子集。

您在真实的面试中是否遇到过这个题?
样例
样例 1:

输入:[0]
输出:
[
[],
[0]
]
样例 2:

输入:[1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]

public class StackAndMin {
    public static void main(String[] args) {
//        System.out.println(strStr("source","se"));
        int[] nums={4,1,2,3};
        List<List<Integer>> subsets = subsets(nums);
        for (List<Integer> list : subsets) {
            for (Integer integer : list) {
                System.out.print(integer+" ");
            }
            System.out.println("---");
        }
//        quickSelect(0, nums.length - 1, nums);
//        System.out.println(nums[0]);
    }

    
    /**
     * @param nums: The integer array.
     * @param target: Target to find.
     * @return: The first position of target. Position starts from 0.
     */
    public static int binarySearch(int[] nums, int target) {
        // write your code here
        if (nums==null || nums.length==0){
            return -1;
        }
        int start=0;
        int end=nums.length-1;
        while (start<=end){
            int index=(start+end)/2;
            if (target<nums[index]){
                //左边
                end=index-1;
            }else if (target==nums[index]){
                //找到前一个小于此值得坐标
                int flag=index;
                if (flag==0 || flag==(nums.length-1)){
                    return flag;
                }
                while (target==nums[flag]){
                    flag--;
                }
                return flag+1;
            }else {
                //右边
                start=index+1;
            }
        }
        return -1;
    }

   
   

    /**
     * @param S: A set of numbers.
     * @return: A list of lists. All valid subsets.
     */
    public static List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> lists=new ArrayList<>();
        List<Integer> list=new ArrayList<>();
        if (nums==null || nums.length==0){
            lists.add(list);
            return lists;
        }
        Queue<List<Integer>> queue=new LinkedList<>();
        /**
         * TODO 对nums排序,这里运用我自己写的快速排序来进行解决
         *
         */
        quickSelect(0, nums.length - 1, nums);
//        Arrays.sort(nums);
//        queue.offer(); 添加
//        queue.poll(); 取出

        queue.offer(list);
        int count=0;
        while (queue.size()>0){
            List<Integer> poll = queue.poll();
            lists.add(poll);

            //用二分查找法查找下标
            int search=0;
            if (poll.size()==0){
               search=-1;
            }else {
                search = binarySearch(nums, poll.get(poll.size() - 1));
            }
            for (int i=search+1;i<nums.length;i++){
                List<Integer> aa=new ArrayList<>();
                aa.addAll(poll);
                aa.add(nums[i]);
                queue.offer(aa);
                count++;
            }
        }
        System.out.println("总共执行了"+count);
        return lists;
    }

    /**
     * 快速排序
     * @param left
     * @param right
     * @param nums
     * @param n
     */
    public static void quickSelect(int start, int end, int[] nums) {
        int pivot = nums[(start + end) / 2];
        int left = start;
        int right = end;
        while (left <= right) {
            while (nums[left] < pivot && left <= right) {
                left++;
            }
            while (nums[right] > pivot && left <= right) {
                right--;
            }
            if (left <= right) {
                //交换
                int swap = 0;
                swap = nums[right];
                nums[right] = nums[left];
                nums[left] = swap;
                left++;
                right--;
            }
        }
        if (right>start) {
            quickSelect(start, right, nums);
        }

        if (left<end) {
            quickSelect(left, end, nums);
        }


    }



}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值