刷leetCode算法题+解析(十四)

为自己加更!明天周末,为了能放下心玩一天,今天要额外刷三道题!

Excel表列名称

题目:给定一个正整数,返回它在 Excel 表中相对应的列名称。例如,
1 -> A
2 -> B
3 -> C
...
26 -> Z
27 -> AA
28 -> AB 
...

示例 1:
输入: 1
输出: "A"
示例 2:
输入: 28
输出: "AB"
示例 3:
输入: 701
输出: "ZY"

怎么说呢,这道题属于解是肯定能解出来,就是优雅不优雅的问题。我发现现在做题真的如果不考虑代码的性能之类的问题,单纯求解还是很简单的。闲话少叙,说思路:我觉得这道题就是很单纯的找规律的问题。现在去仔细看看规律,一会儿回来再说
大行打脸现场再次出现,这道题,我做了一个多小时,没做出来。对,我才说过很简单的,结果卡壳了。重新理一下思路。这可以看作是一个26进制的问题。然后A代表1,B代表2,Z代表26。但是有个问题,就是遇到26的倍数,是不进位的,而只是AZ,BZ这样表示。这就很烦躁。说26进制不26,说27进制也莫得27。我一直就是卡在这里了,递归,while循环,for循环都判断了。不行。除非判断是不是一个被26整除的数。如果是则怎么怎么样。这样还涉及到一个多位问题。之前看题目我以为只是1-702之间呢,结果一提交发现可以好多位,然后推翻重写。最后决定把这个特殊情况提出来单独判断。结果判断来判断去把自己判断蒙了,所以决定出绝招:看大佬思路!
大佬思路很简单,说26进制就是26进制。Z不听话怎么办?盘它呗!不开玩笑了,就是完全把A-Z的意义改变。A表示0.B表示1.C表示2....Z表示25.这样就是一个很成熟的26进制了。如果理解不了可以想想10进制,从0开始到9。10这个数字是没有的!
然后既然26进制完善了,接下来完全可以按照进制的方法来做了。不过要注意一点,实际上代表的数字比咱们进制代表的数值是大1的(回忆一下,题目中A是1.B是2,,,Z是26).所以在每一步用进制换算的时候是要把这个1减去的。只要这个能明白,这个题做起来真三行代码。
上代码:

class Solution {
    public String convertToTitle(int n) {
        StringBuilder sb = new StringBuilder();
        while(n>0){
            //注意这个一定要先-1再取余数,不然先取余再-1会出现莫名其妙的问题。比如都取余0了,再减1.不用我说了吧?
            n--;
            //这里是个巧妙的算法。数字加上字符'A'.再转化成char。
            //'A'本来就是数字,'B'比'A'大1。如果是1+'A'结果转成char就是'B'。以此类推。很容易理解。
            sb.append((char)(n%26+'A'));
            n=n/26;
        }
        return sb.reverse().toString();
    }
}

再一次对思路感觉惊奇,日常一叹吧。真的有时候就差那么一个思路。有了,豁然开朗。没有怎么也想不出来。然后再次感谢leetCode里提供思路的大佬,好人一生平安吧~继续下一题。

多数元素

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。你可以假设数组是非空的,并且给定的数组总是存在多数元素。

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

思路:一点也不夸张的说,不考虑性能问题分分钟做出这道题(我要找回上道题被打的脸)!但是说一点不考虑性能就有点过分了。反正我一下好几个思路。比如存map,值是key,次数是val,累加的。什么时候某个val大于n/2说明那个就是多数元素。还有把数组转成list然后排序。因为确定多数肯定一半以上。直接获取中间的元素看是什么那么多数元素就是什么。然后我要去撸代码测性能啦!
回来了,用我简单粗暴的方法做完了,性能比我想得好得多:

class Solution {
    public int majorityElement(int[] nums) {
        Map map = new HashMap();
        for(int i:nums){
            if(map.containsKey(i)){
                if(map.get(i)+1>=nums.length/2+1){
                    return i;
                }else{
                    map.put(i,map.get(i)+1);
                }               
            }else{
                map.put(i,1);
            }
        }
        //在只要一个元素的情况下会直接走到这
        return nums[0];
    }
}
刷leetCode算法题+解析(十四)_第1张图片
性能结果聊以自慰

第二种想法也写出来了:

class Solution {
    public int majorityElement(int[] nums) {
        //转化成集合
        List list = Arrays.stream(nums).boxed().collect(Collectors.toList());
        //排序
        Collections.sort(list);
        //返回中间位数的元素
        return list.get(list.size()/2);
    }
}

然后两种方法速度都很感人。我要想想怎么优化了。
另外一个小题外话:原来Leetcode是用jdk8运行的。因为我用java 9的方法报错没有这个方法。就是下面这个List.of();


刷leetCode算法题+解析(十四)_第2张图片
image.png

好了,题外话说完了,我要开始研究这个题的最优性能的解了:
我要郑重认个错!!我发现数组能直接排序的,所以我上个方法中先转list再排序纯粹因为知识面窄,会的方法少。

class Solution {
    public int majorityElement(int[] nums) {
        Arrays.sort(nums);
        //返回中间位数的元素
        return nums[nums.length/2];
    }
}

这个是排序取中位数的解。虽然我还没看解析,但是我大概猜测这道题可能是想考数组的快排之类的?因为我现在直接数组排序取中位数运行速度是3ms,想要时间更短我觉得应该就是不要用现成的api?好了,墨迹完毕,我去看解析了。


刷leetCode算法题+解析(十四)_第3张图片
大佬评论

你看我就猜到了,直接用api肯定是不被推荐的,哎,还好我还有一个map计数法。顺便我又顺着大佬的思路解答了一次:
从第一个数开始count=1,遇到相同的就加1,遇到不同的就减1,减到0就重新换个数开始计数,总能找到最多的那个,下面是代码:

class Solution {
    public int majorityElement(int[] nums) {
        int result = nums[0];
        int count = 0;
        for(int i : nums){
           if(i==result || count==0){
              result =i;
              count++;
           }else{
               count--;               
           }
        }
        return result;
    }
}

Excel表序列号

题目:给定一个Excel表格中的列名称,返回其相应的列序号。例如,
A -> 1
B -> 2
C -> 3
...
Z -> 26
AA -> 27
AB -> 28 
...

示例 1:
输入: "A"
输出: 1
示例 2:
输入: "AB"
输出: 28
示例 3:
输入: "ZY"
输出: 701

思路:这个题怎么说呢。撩个狠话吧,今天做不出来我就转行!跟第一个题是一样的。只不过第一题是十进制转化二十六进制,这个题是二十六进制转化成10进制。傻瓜式还原操作。我去直接撸代码了。
做完回来了,半小时左右完成的,性能不好也不坏,反正能对付用。感觉这两道题做完对进制有了一个新的理解了。
其实只要上面第一题会了这个题就是一个逆推的过程。然偶就这样吧。

class Solution {
    public int titleToNumber(String s) {
        //结果
        int result = 0;
        //用来存每一个位数的十进制数字。
        int n = 0;
        for(int i =0;i

因为这个性能还不是最优我还是去看看大神的思路。
哎,人生啊~就是一个不断受打击再站起来的过程。
我以为的不好不坏,其实就是对付而已。大神思路:

    public int titleToNumber(String s) {
        int result = 0;
        for(int i =0;i

准确来讲算上括号五号代码。只能自然不如。
今天就到这了,顺便回忆回忆最近刷了四十多题,虽说都是算法题但是也对一些基础的api有了很大的了解和重新认识,同时对思路的扩展也有一定的作用(虽然离大神还远)。如果写的这些笔记或者说我自己思路的记录稍微帮到了你,记得点个喜欢点个关注呦!顺便祝大家也工作顺顺利利!周末愉快!

你可能感兴趣的:(刷leetCode算法题+解析(十四))