zoukankan      html  css  js  c++  java
  • [LeetCode] Combinations

    题目: Combinations

    1-n个数字中找k个数字的所有不同组合。

    思路:从1-k开始,每次从k开始,让最后面的元素加1,超过了,就让前面一个元素加1,后面一个元素变为前面一个元素的值加1.

    循环知道所有元素都没有超过,则是一种不同的情况。

    例如:n = 6,k = 4;

    1234->1235->1236->1245->1246->1256->1345->1346->1356->1456

    ->2345->...->3456

    package com.example.medium;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;
    
    public class Combinations {
        public List<List<Integer>> combine(int n, int k) {
            List<List<Integer>> list = new LinkedList<>();
            int indexs[] = new int[k];
            int j = 0;
            for(int i = 0;i < k;i++){
                indexs[i] = i;
            }
            while(indexs[0] <= n - k){
                List<Integer> item = new ArrayList<Integer>(k);
                for(int i = 0;i <k;i++){//添加当前的k个元素
                    item.add(i, indexs[i] + 1);
                }
                    list.add(item);
                    j = k - 1;
                    indexs[j]++;//最后一个元素加一
                    while(indexs[j] >= n - k + j + 1){//超过了n则倒数第二个元素加一,然后判断是否超过n,如此循环
                        j--;
                        if(j < 0)break;
                        indexs[j]++;
                    }
                    for(;j >= 0 && j < k - 1;j++)
                        indexs[j + 1] = indexs[j] + 1;
            }
            return list;
        }
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            List<List<Integer>> list = new Combinations().combine(17, 5);
            Iterator<List<Integer>> iterator = list.iterator();
            while(iterator.hasNext()){
                List<Integer> item = iterator.next();
                for(int i = 0;i < item.size();i++)
                    System.out.print(item.get(i) + " ");
                System.out.println();
            }
    
        }
    
    }

     题目:Subsets

    找到给定数组的所有子集;数组中每个元素都不同

    思路:

    和上面一样,不过这次没有固定的k值。

    让k从0开始一直加到n(数组长度),然后按照上面的方法找到所有子集。

    package com.example.medium;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;
    
    public class Subsets {
        public List<List<Integer>> subsets(int[] nums) {
          List<List<Integer>> list = new LinkedList<>();
          int index[] = new int[nums.length];//存储元素下标
          int i = 0,k = 0;
          while (i <= nums.length) {
                    List<Integer> item = new ArrayList<>(i);
                    for (int j = 0; j < i; j++) {//添加子集
                        item.add(j, nums[index[j]]);
                    }
                    list.add(item);
                    k = i - 1;//k减一
                    if(k < 0){//元素个数为i的子集找完了
                        i++;
                        continue;
                    }
                    index[k]++;//最后一个元素的下标加一
                    while(index[k] > nums.length - i + k){
                        k--;//
                        if(k < 0)break;
                        index[k]++;
                    }
                    if(k < 0){//元素个数为i的子集找完了
                        i++;
                        if(i > nums.length)break;
                        for (int j = 0; j < i; j++) {//当i增加时,重新初始化
                            index[j] = j;
                        }
                    }else{
                        for(;k < i - 1;k++)
                            index[k + 1] = index[k] + 1;
                    }
                }
          return list;
        }
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            List<List<Integer>> list = new Subsets().subsets(new int[]{1,2,3,4,5,6});
            Iterator<List<Integer>> iterator = list.iterator();
            while(iterator.hasNext()){
                List<Integer> item = iterator.next();
                for(int i = 0;i < item.size();i++)
                    System.out.print(item.get(i) + " ");
                System.out.println();
            }
    
        }
    
    }

    题目:SubsetsII

    找到给定数组的所有子集;数组中有相同元素。

    思路:

    和上面的相同,但是在查找前先排序,然后每次跳过元素之相同的元素。

    package com.example.medium;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;
    
    /**
     * Given a collection of integers that might contain duplicates, nums, return all possible subsets.
     * 
     * Note: The solution set must not contain duplicate subsets.
     * 
     * For example,
     * If nums = [1,2,2], a solution is:
     * 
     * [
     *   [2],
     *   [1],
     *   [1,2,2],
     *   [2,2],
     *   [1,2],
     *   []
     * ]
     * @author qfp
     *
     */
    public class SubSets2 {
        public List<List<Integer>> subsetsWithDup(int[] nums) {
            List<List<Integer>> list = new LinkedList<List<Integer>>();
            Arrays.sort(nums);
            int[] index = new int[nums.length];//记录当前情况的下标
            int i = 0,k = 0;//i表示子集中元素的个数
            while(i <= nums.length){
                List<Integer> item = new ArrayList<Integer>(i);
                for (int j = 0; j < i; j++) {//将当前情况添加进去
                    item.add(j, nums[index[j]]);
                }
                list.add(item);
                k = i - 1;//更新当前子集个数为i时,新的可能的子集
                if(k < 0){//当i = 0时,只有一个空集
                    i++;
                    continue;
                }
                //先更新id最大的元素,去重
                while(index[k] < nums.length - 1 && nums[index[k]] == nums[index[k] + 1])index[k]++;
                index[k]++;
                while(index[k] > nums.length - i + k){
                    k--;//
                    if(k < 0)break;//k小于0时,表示个数为i的子集全部找到了
                    while(index[k] < nums.length - 1 && nums[index[k]] == nums[index[k] + 1])index[k]++;
                    index[k]++;
                }
                if(k < 0){
                    i++;
                    if(i > nums.length)break;
                    for (int j = 0; j < i; j++) {//当i增加时,重新初始化
                        index[j] = j;
                    }
                }else{
                    for(;k < i - 1;k++)
                        index[k + 1] = index[k] + 1;
                }
            }
            return list;
        }
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            List<List<Integer>> list = new SubSets2().subsetsWithDup(new int[]{1,2,2,1,1});
            Iterator<List<Integer>> iterator = list.iterator();
            while(iterator.hasNext()){
                List<Integer> item = iterator.next();
                for(int i = 0;i < item.size();i++)
                    System.out.print(item.get(i) + " ");
                System.out.println();
            }
    
        }
    
    }
  • 相关阅读:
    VMware克隆虚拟机
    3种Redis分布式锁的对比
    高并发下缓存与数据库双写不一致解决方案
    30分钟Maven入门到精通
    Linux安装rabbitmq (解决guest无法登陆问题)
    RocketMQ高性能原理(pushConsumer,CommitLog,ZeroCopy)
    XA 分布式事务原理(转)
    SpringBoot学习(八)RestTemplate/WebClient 调用REST服务、Validation校验和发邮件
    @Valid和@Validated的总结区分(转)
    Dubbo 同步调用原理(转)
  • 原文地址:https://www.cnblogs.com/yeqluofwupheng/p/6685394.html
Copyright © 2011-2022 走看看