(题解)《算法零基础100讲》(第32讲) 多维枚举(二) - 进阶(缺少最后一题)

1、两个数组间的距离值(leetcode1385

两重for循环,外层枚举arr1的元素,二层枚举arr2的元素,设置一个amount值来记录不符合条件的arr1元素数量,最后返回arr1的长度 - amount的数值。

class Solution {
    public int findTheDistanceValue(int[] arr1, int[] arr2, int d) {
        int x = arr1.length, y = arr2.length,amount = 0 ;//amount不符合条件的元素个数
        for(int i = 0 ; i < x ; i ++ )
        {
            for(int j = 0 ; j < y ; j ++)if(Math.abs(arr1[i] - arr2[j]) <= d)
            {
                amount++;
                break;
            }
        }
        return x - amount;
    }
}

2、顺次数(leetcode1291

我们可以发现相同位数的顺次数之间是相差多个1的,比如123和234是相差111,4567和5678也是相差1111。所以我们可以先计算出基于low位数的最小顺次数(比如low是455,那么三位数的最小顺次数就是123),然后循环加对应位数的1,判断是否属于low和high的范围。还有一个判断条件就是如果顺位数的个位为0的话,就要将顺位数的位数加一位,比如原本是789,加了111后就变成790,就不符合了,要将它变成1234.

class Solution {
    public  List<Integer> sequentialDigits(int low, int high) {
        //template表示12345的开头,template2表示11111的加数
        int low_ex = low, template = 0, template2 =0,k = 1;
        List<Integer> li = new ArrayList<>();
        //计算基于low和high的最小顺次数和连续1的加数
        while(low_ex != 0)
        {
            template = template * 10 + k;
            template2 = template2 * 10 + 1;
            k ++;
            low_ex /= 10;
        }
        int i = template;
        //遍历基于low和high之间的顺次数
        while(i <= high)
        {
            if(i % 10 == 0)
            {
                template = template * 10 + k;
                k ++;
                i = template;
                template2 = template2 * 10 + 1;
                continue;

            }
            else if(low <= i && i <= high)li.add(i);
            i += template2;

        }
        return li;
    }
}

3、下一个更大的数值平衡数(2048

可以使用HashMap统计大于n的每个数中出现的数字,如果是HashMap[i] == i , 就是平衡数,第一个出现的就是结果。

class Solution {
        public  int nextBeautifulNumber(int n) {

        Map<Integer,Integer> map;
        for(int i = n ; ;i ++ )
        {
            int template = i ;
            map = new HashMap<>();
            while(template != 0)
            {
                if(!map.containsKey(template % 10))map.put(template % 10 , 1);
                else
                {
                    int num = map.get(template % 10);
                    map.put(template % 10 , ++num);
                }
                template /= 10;
            }
            template = i;
            while (template != 0)
            {
                if(map.get(template % 10) != template % 10)break;
                template /= 10;
            }
            if(template == 0)
            {
                if(i > n)return i;
            }

        }
    }
}

4、两个数组的交集(leetcode349

这题可以利用HashSet来分别统计两个数组的数字,然后以其中长度较短的HashSet为标准去判断另一个HashMap的交集。

class Solution {
        public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set1 = new HashSet<>();
        Set<Integer> set2 = new HashSet<>();
        for(int i : nums1)
        {
            set1.add(i);
        }
        for(int i : nums2)
        {
            set2.add(i);
        }
        List<Integer> li = new ArrayList<>();
        if(set1.size() >= set2.size())
        {
            Iterator<Integer> iterator = set2.iterator();
            while(iterator.hasNext())
            {
                int num = iterator.next();
                if(set1.contains(num))li.add(num);
            }
        }
        else
        {
            Iterator<Integer> iterator = set1.iterator();
            while(iterator.hasNext())
            {
                int num = iterator.next();
                if(set2.contains(num))li.add(num);
            }
        }
        int []result = new int[li.size()];
        for(int i = 0 ; i < result.length ; i ++ )result[i] = li.get(i);
        return result;
    }
}

5、统计特殊四元组(leetcode1995

这题使用了英雄哥开篇介绍的哈希降维方法。

class Solution {
    public  int countQuadruplets(int[] nums) {
        Map<Integer , Integer> map = new HashMap<>();
        int amount = 0;
        for(int c = 0 ; c < nums.length ; c ++)
        {
            for(int b = 0 ; b < c ; b ++)
            {
                for(int a = 0 ; a < b ; a ++)
                {
                    if(!map.containsKey(nums[a] + nums[b]))map.put(nums[a] + nums[b] , 1);
                    else
                    {
                        int num = map.get(nums[a] + nums[b]);
                        map.put(nums[a] + nums[b],++num);
                    }
                }
            }
            for(int d = c + 1 ; d < nums.length ; d ++)
            {
                if(map.containsKey(nums[d] - nums[c]))
                {
                    amount += map.get(nums[d] - nums[c]);
                }

            }
            map.clear();
        }
        return amount;
    }
}

6、两个数组的交集(leetcode1566

思路就是它要匹配连续的重复子序列,那么数组中就一定有k * m长度的一段是以模式重复的,比如使1 2重复3次,那么数组中就要有一段是121212,所以只需要找到这一段就好了。
从arr数组头i = 0开始遍历,设置一个loc的值用来记录重复子序列的下标(也就是121212的下标),接着判断arr[i +loc] == arr[i + loc % m] ,如果相等就loc++,继续往下,如果不相等就i++,然后继续从loc=0开始。那么为什么要loc % m呢?因为是长度为m的子序列(比如1 2,长度为2)重复k(3)次(即1 2 1 2 1 2),(假设当前loc为 4)loc % m(4 % 2 ) 得到 0 就可以定位到 下标为0,即数字 1,用来判断与loc[i + loc]是否相等。

class Solution {
        public boolean containsPattern(int[] arr, int m, int k) {
        //要匹配的长度
        int tem_len = m * k , loc = 0;
        for(int i = 0 ; i + tem_len <= arr.length ; i ++)
        {
            for(loc = 0 ; loc < tem_len ; loc ++)
            {
                //取余是为了定位到模式串中
                if(arr[i + loc] != arr[i + loc % m])break;
            }
            if(loc == m * k)return true;
        }
        
        return false;
    }
}

7、(困难)分割数组的最多方案数leetcode2025(待补充)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值