其他

作者: isuntong | 来源:发表于2020-02-07 22:47 被阅读0次

剑指offer所有的题目总结

牛客

  1. 整数中1出现的次数

求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

编程之美上给出的规律:
1、 如果第i位(自右至左,从1开始标号)上的数字为0(小于x),则第i位可能出现1的次数由更高位决定(若没有高位,视高位为0),等于更高位数字 * 当前位数的权重10^(i-1)。

2、如果第i位上的数字为1(等于x),则第i位上可能出现1的次数不仅受更高位影响,还受低位影响(若没有低位,视低位为0),等于更高位数字 * 当前位数的权重10^(i-1)+(低位数字+1)。

3、如果第i位上的数字大于1(大于x),则第i位上可能出现1的次数仅由更高位决定(若没有高位,视高位为0),等于(更高位数字+1) * 当前位数的权重10^(i-1)。

这个思路中,如果不是求1出现的次数,而是求其他1-9任意一个次数,就是比较大于、等于、小于这个数就行了,分别对应上边的三条规则。0的出现次数需要余外计算。

X的数目
这里的 X∈[1,9] ,因为 X=0 不符合下列规律,需要单独计算。

首先要知道以下的规律:
从 1 至 10,在它们的个位数中,任意的 X 都出现了 1 次。
从 1 至 100,在它们的十位数中,任意的 X 都出现了 10 次。
从 1 至 1000,在它们的百位数中,任意的 X 都出现了 100 次。

依此类推,从 1 至 10^ i ,在它们的左数第二位(右数第 i 位)中,任意的 X 都出现了 10^(i-1) 次。

这个规律很容易验证,这里不再多做说明。
接下来以 n=2593,X=5 为例来解释如何得到数学公式。从 1 至 2593 中,数字 5 总计出现了 813 次,其中有 259 次出现在个位,260 次出现在十位,294 次出现在百位,0 次出现在千位。

public int NumberOf1Between1AndN_Solution(int n) {
        int low,cur,temp,i=1;
        int high = n;//记录高位数
        int total = 0; //总的1的数量
        if(n < 1)
            return 0;
        while(high!=0) {
            //记忆2593 此时i=2,依次拆分25 9 3
            high = n/powerBaseof10(i);//// 获取第i位的高位
            temp = n%powerBaseof10(i);
            cur = temp/powerBaseof10(i-1);// 获取第i位
            low = temp%powerBaseof10(i-1);// 获取第i位的低位
            if(cur ==1) {
                total += high * powerBaseof10(i-1) + low +1;
            }
            else if (cur > 1) {
                total += (high + 1) * powerBaseof10(i -1);
            }
            else {
                total += high * powerBaseof10(i-1);
            }
            i++;
        }
        return total;
    }
    //就是求10^base次方
    public int powerBaseof10(int base) {
        return (int)Math.pow(10, base);
    }v
  1. 扑克牌顺子

LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张_)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。

public boolean isContinuous(int [] numbers) {
        if(numbers == null || numbers.length ==0)
            return false;
        int zero = 0;//记录0的个数
        int diff = 0;//记录空缺的数
        Arrays.sort(numbers);
        
        for (int i = 0; i < numbers.length -1; i++) {
            if(numbers[i] == 0) {
                zero++; //找不到非0的就继续下一次循环
                continue;
            }
            if (numbers[i] != numbers[i+1]) {
                diff += numbers[i+1] - numbers[i] -1 ;//4 和 8,中间空缺3
            }
            else
                return false;//说明有对子,肯定不是顺子
                
        }
        if(diff<= zero)
            return true;//如果diff小于zero,那么zero放在最后就行,因为任意值
        return false;
    }
  1. 孩子们的游戏(圆圈中剩下的数)

每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)

如果没有小朋友,请返回-1

public int LastRemaining_Solution(int n, int m) {
        LinkedList<Integer> list = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            list.add(i);
        }
        int bt = 0;
        while(list.size() >1) {
            //// 删除报数为m-1的人(从0开始)
            //解析看前面
            bt = (bt + m -1)%list.size();
            list.remove(bt);
        }
        return list.size()==1?list.get(0):-1;
    }

递归方法:(注意推到公式)

public int LastRemaining_Solution(int n, int m) {
        if (m < 1 || n < 1)
            return -1;
        int last = 0;
        // i代表有目前有个人
        for (int i = 2; i <= n; i++)
            last = (last + m) % i;
        return last;
    }
  1. 替换空格

请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

String s = str.toString();
        
        if(s.equals("")) {
            return s;
        }
        
        StringBuffer sb = new StringBuffer();
        
        for(int i=0;i<s.length();i++) {
            if(s.charAt(i) == ' ') {
                sb.append("%20");
            }else {
                sb.append(s.charAt(i));
            }
        }
        
        return sb.toString();
  1. 斐波那契数列

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。
n<=39

public int Fibonacci(int n) {       
        if(n<=1) {
            return n;
        }
        
        int a = 1;
        int b = 1;
        int tmp = 0;
        for(int i=2;i<n;i++) {
            tmp = a + b;
            a = b;
            b = tmp;
        }
        return b;
    }

递归会用时更多

  1. 跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

int count = 0;
    
    public int JumpFloor(int target) {
        tiao(1,target);
        tiao(2,target);
        return count;
    }

    private void tiao(int sum, int target) {
        // TODO 自动生成的方法存根
        if(sum > target) {
            return;
        }
        
        if(sum == target) {
            count++;
            return;
        }
        
        tiao(sum+1,target);
        tiao(sum+2,target);
    }
  1. 变态跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

int count = 0;
    
    public int JumpFloorII(int target) {
        
        for(int i=1;i<target+1;i++) {
            tiao(i,target);
        }

        return count;
    }

    private void tiao(int sum, int target) {
        // TODO 自动生成的方法存根
        if(sum > target) {
            return;
        }
        
        if(sum == target) {
            count++;
            return;
        }
        
        for(int i=1;i<target+1;i++) {
            tiao(sum+i,target);
        }
    }

循环加递归去跳

答案:

public class Solution {
    public int JumpFloorII(int target) {
        int res = 1;
        for(int i =1;i <=target-1;i++){
            
            res = res * 2;
            
        }
        return res;
    }
}
  1. 矩形覆盖

我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

int res = 0;
        if(target == 0)
            return 0;
        else if(target == 2)
            return 2;
        else if(target ==1)
            return 1;
        else
            res = RectCover(target - 1) + RectCover(target-2);
        return res;
  1. 数值的整数次方

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

保证base和exponent不同时为0

//本题注意的是exponent小于0 或者 等于 0 的情况 还有base为0的情况
        double result = 1;
        if(exponent < 0){
            base = 1/base;
            exponent = (-1) * exponent;
            for (int i = 1; i <= exponent; i++) {
                result = result *base;
            }
        }
        else{
            for (int i = 1; i <= exponent; i++) {
                result = result *base;
            }
        }
        return result;

  1. 顺时针打印矩阵

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

public  ArrayList<Integer> printMatrix(int [][] matrix){
        ArrayList<Integer> list = new ArrayList<Integer>();
        int topRow = 0;
        int topCol = 0;
        int downRow = matrix.length - 1;
        int downCol = matrix[0].length - 1;
        while (topRow <= downRow && topCol <= downCol) { //当满足左上角的小于等于右下角就可以循环
            printCircle(list, matrix, topRow++, topCol++, downRow--, downCol--);
        }
        return list;
    }
    
    public  void printCircle(ArrayList<Integer> list, int [][] matrix, int topRow, int topCol, int downRow, int downCol) {
        if (topRow == downRow) { //子矩阵只有一行的时候
            for (int i = topCol; i <= downCol; i++) {//注意循环开始的条件,是从这一列开始,不是从零
                list.add(matrix[topRow][i]);
            }
        }
        else if (topCol == downCol) {//子矩阵只有一列的时候
            for (int i = topRow; i <= downRow; i++) {//
                list.add(matrix[i][topCol]);
            }
        }
        else { //其他的情况下
            int currentRow = topRow;
            int currentCol = topCol;
            while (currentCol != downCol) {//左到右 本行最后一个不访问,在下个循环里面。如图
                list.add(matrix[topRow][currentCol]);
                currentCol++;
            }
            while (currentRow != downRow) {//上到下0
                list.add(matrix[currentRow][downCol]);
                currentRow++;
            }
            while (currentCol != topCol) {//右到左
                list.add(matrix[downRow][currentCol]);
                currentCol--;
            }
            while (currentRow != topRow) {//下到上
                list.add(matrix[currentRow][topCol]);
                currentRow--;
            }
        }
    }

自己弄循环条件没搞好。。。

  1. 最小的k个数

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        
        if(k > input.length) {
            return list;
        }
        
        Arrays.sort(input);

        for(int i=0;i<k;i++) {
            list.add(input[i]);
        }
        return list;
    }
    

答案用大顶堆。。。

  1. 丑数

把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

public int GetUglyNumber_Solution(int index) {
        if(index <= 0)
            return 0;
        int [] res = new int[index];
        res[0] = 1;//先把1放入
        int m2 = 0;//控制乘以2的位置,假设得到一个丑数是乘以2得到的,
                    //那么下一次就是数组中的下一个丑数可能达到。
        int m3 = 0;
        int m5 = 0;
        for (int i = 1; i < index; i++) {
            int min = Math.min(res[m2]*2, Math.min(res[m3]*3, res[m5]*5));
            res[i] = min;//最小的那个作为当前的丑数
            //判断是由谁乘以得到的
            if(res[m2] *2 == min)//假设res[1]是乘以2得到的丑数,那么下一次就要判断
                              //是否是res[2]乘以2可能得到丑数,所以就要++
                m2++;
            if(res[m3]*3 == min)
                m3++;
            if(res[m5]*5 == min)
                m5++;
        }
        return res[index - 1];
    }

相关文章

  • 其他都是其他

    最近看到一个新闻报道,有些人沉迷在电视剧中,无法自拔,沉迷于剧中人的颜值,沉迷于剧中人的生活,沉迷于剧中人对待爱人...

  • 其他

    01吃完饭回来的路上看到大一时的英语老师,依然是酷酷的样子,白头发却多了很多。这两年对我来说是沧海桑田,对其他人又...

  • 其他

    如果不想聊時政聊聊愛情也是可以的首先你的荷爾蒙得调高這樣才能體會到愛情之美妙 其次你得遇到一個人比如我這樣的咱倆得...

  • 其他

    ContentProvider相关 涉及到拍照相关的问题可参照此example TakePicAndGallery...

  • 其他

    待这一年的尽头,我们来向后看看,再来写下它们。

  • 其他

    1.数--二叉查找树 2.反向索引 3.傅里叶变换 4.并行算法 5.MapReduce(分布式算法) 映射函数m...

  • 其他

    HydrogenOS 3.0 |XDA |下载 Flyme 6 |下载 Mi-Room |下载

  • 其他

    Git常用命令mac常用命令Linux 常用命令汇总Linux 常用命令0Linux 常用命令1--ls命令

  • 其他

    本网讯(通讯员任智琪 许唯佳)3月28日下午,武汉市东湖新技术开发区疾控中心刘丽、姜丹两位专家应邀在图书馆3号报告...

  • 其他

    使用Charles进行HTTPS抓包1.配置2.Charles抓取https时一直显示unknown

网友评论

      本文标题:其他

      本文链接:https://www.haomeiwen.com/subject/ejlvxhtx.html