第二课刷题

【题目一】

规定1是丑数,其他的数如果只含有2或3或5的因子,那么这个数也是丑数。

比如依次的丑数为:1,2,3,4,5,6,8,9,10,12,15...

求第n个丑数

【思路】

判定某个数是否为丑数:

  对该数,如果模2==0,则除以2,直到模2不等于0,即目的是将该数的2因子全部消去,对3因子和5因子也处于同样策略,直到最后该数如果=1,则为丑数。

算法:

根据题意,设计三个指针,分别为X2指针,X3指针,X5指针,初始都处于0位置。该指针指向某个数表示可由某个数乘以该指针得到新的丑数。

从1出发,每次选取三个指针与其分别指向的数的乘积可获得的三个数中的最小一个,然后将被选择的指针后移至下个丑数。

时间复杂度为O(n)

【Code】

public static int FindUglyNum(int n)
    {
        int[] help = new int[n];
        help[0] = 1;
        int i2 = 0;
        int i3 = 0;
        int i5 = 0;
        int index = 1;
        while(index<n)
        {
            help[index] = Math.min(2*help[i2], Math.min(3*help[i3], 5*help[i5]));
            if(help[index]==2*help[i2])
                i2++;
            if(help[index]==3*help[i3])
                i3++;
            if(help[index]==5*help[i5])
                i5++;
            index++;
        }
        return help[index-1];
    }

【拓展】

这个丑数规则是题干设定的,以后遇到说给你一个规则让你生成一个序列,求第n个数。你就想想后面的数怎么由之前的数得到的,按这个出发点去分析。

 

【题目四】

如果str1和str2包含的字符种类一样,并且每种字符的个数也一样,那么str1和str2算作变形词。

给定一个字符类型的数组,请把变形词分组。比如

输入:

["eat", "tea", "tan", "ate", "nat", "bat"]

输出:

[

["ate", "eat","tea"],

["nat","tan"],

["bat"]

]

注意:所有的字符都是小写

【思路】

1、数据样本是26个小写字符,统计每个词的每个字符出现的次数,将其形成一个顺序串,对互为变形词的单词,其串是相同的。

2、形成串:使用一个26长度的char数组记录,其中’0’表示’a’,以此类推,对char数组的内容连在一起形成一个串。

提示点:

关注数据样本状况,是优化代码的点

【Code】

public static List<List<String>> groupAnagrams(String[] strs)
    {
        HashMap<String, List<String>>map = new HashMap<String, List<String>>();
        //key是为单词打造的字符串,value是属于该字符串的单词集合。其元素都互为变形词
        for(String str:strs)
        {
            int[] record = new int[26];
            //统计每个单词的字符出现的个数
            for(char cha:str.toCharArray())
                record[cha-'a']++;
            //为每个单词按a~z出现的顺序打造一个字符串,如果是变形词其打造的字符串是一样的
            StringBuilder builder = new StringBuilder();
            for(int value:record)
                builder.append(String.valueOf(value)).append("_");
            String key = builder.toString();
            //如果该字符串没有出现过,则新开辟一个
            if(!map.containsKey(key))
                map.put(key, new ArrayList<String>());
            map.get(key).add(str);//将生成key的str加入到变形词集合当中
        }
        //将全部集合汇总
        List<List<String>> res = new ArrayList<List<String>>();
        for(List<String> list:map.values())
            res.add(list);
        return res;
    }

 

【题目五】

给定一个整数矩阵matrix,每个位置你可以向左、右、下、上移动,找到其中最长的递增路径。

例如:

matrix = [

[9,9,4],

[6,6,8],

[2,1,1]

]

返回4

最长路径是[1, 2, 6, 9].

【思路】

1、思考该问题是否为无后效性问题。无后效性问题:该子状态不由前面状态决定,只由自己的参数决定,不论是谁调用该子状态,其返回值都是一致的。

2、先写出该问题的暴力搜索解,再一步步改为动态规划。

【Code】

public static int max(int[][] matix)
    {
        int max = 0;
        int[][] dp = new int[matix.length][matix[0].length];
        for(int row = 0;row<matix.length;row++)
        {
            for(int col = 0;col<matix[0].length;col++)
            {
                max = Math.max(max, process(matix,dp, row, col));
            }
        }
        return max;
    }
    public static int process(int[][] matix,int[][] dp,int row,int col)
    {
        if(dp[row][col]==0)
        {
            dp[row][col]=1;//原地不动的长度   
            if(matix[row][col-1]>matix[row][col] && col>0)
            {
                dp[row][col] = Math.max(dp[row][col], process(matix,dp, row, col-1)+1);
            }
            if(matix[row][col+1]>matix[row][col] && col<matix[0].length-1)
            {
                dp[row][col] = Math.max(dp[row][col], process(matix, dp,row, col+1)+1);
            }
            if(matix[row-1][col]>matix[row][col] && row>0)
            {
                dp[row][col] = Math.max(dp[row][col], process(matix,dp, row-1, col)+1);
            }
            if(matix[row+1][col]>matix[row][col] && row<matix.length)
            {
                dp[row][col] = Math.max(dp[row][col], process(matix, dp,row+1, col)+1);
            }
        }
        return dp[row][col];
    }

 

posted @ 2021-03-03 09:59  γGama  阅读(51)  评论(0)    收藏  举报