算法训练营—SecondWeekend

🍉题目一:斐波那契步数

链接

https://www.nowcoder.com/practice/18ecd0ecf5ef4fe9ba3f17f8d00d2d66?tpId=85&&tqId=29846&rp=1&ru=/activity/oj&qru=/ta/2017test/question-ranking

题目解析

本题是对于Fibonacci数列的一个考察,Fibonacci数列的性质是第一项和第二项都为1,后面的项
形成递归:F(n) = F(n - 1) + F(n - 2)。

解题思路

【解题思路】:
本题可以通过先找到距离N最近的两个Fibonacci数,这两个数分别取自距离N的最近的左边一个
数L和右边一个数R,然后通过min(N - L, R - N)找到最小步数

代码实现

/**
 * 最小斐波那契步数
 */
import java.util.*;
public  class TrueMain2{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int a = scanner.nextInt();
        int[] array = new int[10000];
        array[0] = 0;
        array[1] = 1;
        int i = 1;
        while(array[i]<a){
            i++;
            array[i] = array[i-1]+array[i-2];
        }
        if(a==array[i]){
            System.out.print(0);
        }else{
            int b = a - array[i-1];
            int c = array[i] - a;
            if(b>c){
                System.out.print(c);
            }else{
                System.out.print(b);
            }
        }
    }
}

做这道题的时候,不要想那么复杂,我第一遍做的时候,会想创建一个斐波那契数组,然后将这个输入的数字遍历数组,然后在判断最小步数,这样反而变得很复杂,只需要用一个while循环即可

🥝题目二:合法括号序列判断

链接

https://www.nowcoder.com/practice/d8acfa0619814b2d98f12c071aef20d4?tpId=8&&tqId=11039&rp=1&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking

题目解析

本题考查的是对栈的应用

解题思路

用栈结构实现,栈中存放左括号,当遇到右括号之后,检查栈中是否有左括号,如果有则出栈,
如果没有,则说明不匹配。

代码实现

import java.util.*;

public class Parenthesis {
    public boolean chkParenthesis(String A, int n) {
        // write code here
        if(A.length()%2!=0 ){
            return false;
        }
      
        Stack<Character> stack = new Stack();
        for(int i = 0;i<A.length();i++){
            if(A.charAt(i)=='('){
                stack.push(A.charAt(i));
            }else if(A.charAt(i)==')'){
                if(stack.isEmpty()){
                    return false;
                }else{
                    stack.pop();
                }
            }
        }
        return stack.isEmpty();
    }
}

此题主要的思路就是运用栈的思路判断,如果栈中没有括号,此时如果此时数组的值是右括号,显然这是不合法的,所以返回false,如果是左括号,那就入栈,不使用栈也可以做,但是使用栈容易理解,如果你学了数据结构的话

🍓题目三:两种排序方法

链接

https://www.nowcoder.com/questionTerminal/839f681bf36c486fbcc5fcb977ffe432

题目解析

题目清晰明了,不做过多解答

解题思路

归根结底还是遍历字符串,需要注意的是我们需要把输入进来的字符串放到一个字符串数组里,需要运用一些字符串输入的知识

代码实现

/**
 * 字符串的两种排序
 */

import java.util.*;
import java.io.*;
public class TrueMain3{
    public static int SortZifuchuan(String[] str){
        for(int i=0;i<str.length-1;i++){
        //字符串之间的比较需要使用compareTo方法
            if(str[i].compareTo(str[i+1])>0){
                return 0;
            }
        }
        return 1;
    }
    public static int SortLength(String[] str){
        for(int i=0;i<str.length-1;i++){
            if(str[i].length()>str[i+1].length()){
                return 0;
            }
        }
        return 1;
    }
    public static void main(String[]args)throws IOException{
        BufferedReader bi = new BufferedReader(new InputStreamReader(System.in));
        Scanner scanner = new Scanner(System.in);
        int n = Integer.parseInt(scanner.nextLine());
        String[] str = new String[n];
        for(int i=0;i<n;i++){
            str[i] = scanner.nextLine();
        }
        int sum =SortZifuchuan(str)+SortLength(str);
        if(sum==0){
            System.out.print("none");
        }else if(sum==1){
            if(SortZifuchuan(str)==1&&SortLength(str)==0){
                System.out.print("lexicographically");
            }
            if(SortZifuchuan(str)==0&&SortLength(str)==1){
                System.out.print("lengths");
            }
        }
        if(sum==2){
            System.out.print("both");
        }

    }
}

🍎题目四:最小公倍数

链接

https://www.nowcoder.com/questionTerminal/dc0e22ddf9974db2b78ed6f65088f8b3

题目解析

不做解释

解题思路

最小公倍数=两个数相乘/最大公约数,即此题就是求最大公约数的题

代码实现

public class TrueMain4{

    public static void swap(int a ,int b){
        int tmp = 0;
        if(a<b){
            tmp = b;
            b = a;
            a =tmp;
        }
    }
    public static void main(String[]args){
        Scanner scanner = new Scanner(System.in);
        int a = scanner.nextInt();
        int b = scanner.nextInt();
        swap(a,b);
        int tmp = 0;
        int a1 = a;
        int b1 = b;
        while(a%b!=0){
            tmp = b;
            b = a%b;
            a= tmp;
        }
        System.out.print(a1*b1/b);
    }
}

我们在求最大公约数的时候需要保证a始终大于b,所以需要写一个函数来交换a和b的值

🍑题目五:另类加法

链接

https://www.nowcoder.com/practice/e7e0d226f1e84ba7ab8b28efc6e1aebc?tpId=8&&tqId=11065&rp=1&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking

题目解析

本题的意思是自己实现加法,不适用现成的运算符,考察大家对于运算符的灵活运用

解题思路

本题可以通过位运算实现,具体实现如下:

  1. 二进制位异或运算相当于对应位相加,不考虑进位 比如: 1 ^ 1 = 0 —> 1 + 1 = 0 (当前位值
    为0,进一位) 1 ^ 0 = 1 —> 1 + 0 = 1 (当前位值为1) 0 ^ 0 = 0 —> 0 + 0 = 0 (当前位值为0)
  2. 二进制位与运算左移一位相当于对应位相加之后的进位 比如: 1 & 1 = 1 —> 1 + 1 = 0 (当前位的值进一位) 1 & 0 = 0 —> 1 + 0 = 1 (当前位的值不进位) 0 & 0 = 0 —> 0 + 0 = 0 (当前位的值不进位)
  3. 两个数相加:对应二进制位相加的结果 + 进位的结果 比如:3 + 2 --> 0011 + 0010 --> 0011^ 0010 + ((0011 & 0010) << 1) —> (0011 ^ 0010) ^ ((0011 & 0010) << 1), 当进位之后的结
    果为0时,相加结束

代码实现

import java.util.*;
public class UnusualAdd {
    public int addAB(int A, int B) {
         if (B == 0) {
            return A;
        }
        int sum = 0;
        int carray = 0;
        while (B != 0) {
            sum = A ^ B;
            carray = (A & B) << 1;
            A = sum;
            B = carray;
        }
        return A;
    }
}

🍌题目六:走方格的方案数

链接

https://www.nowcoder.com/practice/e2a22f0305eb4f2f9846e7d644dba09b?tpId=37&&tqId=21314&rp=1&ru=/activity/oj&qru=/ta/huawei/question-ranking

题目解析

本题为求取路径总数的题目,一般可以通过递归求解,对于复杂的问题,可以通过动态规划求解。此题比较简单,可以通过递归解答。

解题思路

请添加图片描述

代码实现

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNextInt()){
            int n = scanner.nextInt();
            int m = scanner.nextInt();
             System.out.print(add(m,n));
        }
    }
    public static int add(int n,int m){
        if(n==1&&m>=1 || n>=1&&m==1){
            return m+n;
        }
            return add(n-1,m)+add(n,m-1);
        }
}

这道题看起来虽然很麻烦,但是如果运用了递归的思想,问题就会被分成很多小问题,这样理解起来就容易多了

🥥题目七:井字棋

链接

https://www.nowcoder.com/practice/e1bb714eb9924188a0d5a6df2216a3d1?tpId=8&&tqId=11055&rp=1&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking

题目解析

井字棋,是一种在3*3格子上进行的连珠游戏,三个相同就代表获胜。

解题思路

井字棋有四种情况表示当前玩家获胜,1代表当前玩家棋子 1. 行全为1, 即行的和为3 2. 列全为
1, 列的和为3 2. 主对角全为1, 对角和为3 副对角全为1 对角和为3
3. 如果扩展为N*N的话,
判断和是否等于N,下面代码适用任何情况

代码实现

import java.util.*;

public class Board {
    public boolean checkWon(int[][] board) {
        // write code here
        int sum = 0;
        int size = board.length;
        for(int i=0;i<board.length;i++){
            sum = 0;
            for(int j=0;j<board.length;j++){
                sum+=board[i][j];
            }
            if(sum==board.length){
                return true;
            }
        }
        for(int i=0;i<board.length;i++){
            sum = 0;
            for(int j=0;j<board.length;j++){
                sum+=board[j][i];
            }
            if(sum==board.length){
                return true;
            }
        }
        sum = 0;
        for(int i=0;i<board.length;i++){
            sum+=board[i][i];
        }
         if(sum==board.length){
                return true;
            }
        sum = 0;
        for(int i=0;i<board.length;i++){
            sum+=board[i][board.length-i-1];
        }
        if(sum==board.length){
                return true;
            }
        return false;
    }
   
}

对于这道题,我们需要知道的是,我们不是在下棋,而是在判定玩家是否胜利,这和我们之前做的那个放蛋糕的那个题不同,那个题的二维数组是空的,需要我们去赋值,这个不用只需要判定给的数组行列对角线的值是否符合获胜的条件即可

🥭题目八:密码强度等级

链接

https://www.nowcoder.com/practice/52d382c2a7164767bca2064c1c9d5361?tpId=37&&tqId=21310&rp=1&ru=/activity/oj&qru=/ta/huawei/question-ranking

题目解析

本题考查的是同学们对于字符的使用。

解题思路

这里对于不同种类的字符得分不同,同学们可以现对每一个维度进行单独判断,即对于长度,字母,数字,符号单独判断,最后把所有的单项值根据题目要求相加,输出对应的安全级别

代码实现

import java.util.*;
public class Main {
    public static void main(String[]args) {
        Scanner scanner = new Scanner(System.in);
        String str = scanner.nextLine();
        int score = 0;
        if (str.length() <= 4) {
            score += 5;
        } else if (str.length() >= 5 && str.length() <= 7) {
            score += 10;
        } else {
            score += 25;
        }
       
        int count1 = 0;
        int count2 = 0;
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) >= 65 && str.charAt(i)  <= 90) {
                count1 = 1;
            }
            if (str.charAt(i)  >= 97 && str.charAt(i)   <= 122) {
                count2 = 1;
            }
        }
        if (count1 == 1&& count2==0) {
            score += 10;
        } else if (count2 == 1&& count1==0) {
            score += 10;
        } else if (count1 == 1 && count2 == 1) {
            score += 20;
        }else{
            score+=0;
        }
       
        int count3 = 0;
        for (int i = 0; i < str.length(); i++){
            if (str.charAt(i) - '0' >= 0 && str.charAt(i) - '0' <= 9){
                count3++;
            }
        }
        if(count3==0){
            score+=0;
        }else if (count3==1){
            score+=10;
        }else if(count3>1){
            score+=20;
        }
         
        int count4 = 0;
        for (int i = 0; i < str.length(); i++){
            if(!(str.charAt(i) >= 65 && str.charAt(i)  <= 90)&&
               !(str.charAt(i)  >= 97 && str.charAt(i)   <= 122)&&
              !(str.charAt(i) - '0' >= 0 && str.charAt(i) - '9' <= 9)){
                count4++;
            }
    }
        if(count4 ==0){
            score+=0;
        }else if(count4==1){
            score+=10;
        }else if(count4>1){
            score+=25;
        }
        
        if(count1==1&&count2==0||count2==1&&count1==0 && count3>=1 && count4==0){
            score+=2;
        }else if(count1==1&&count2==0||count2==1&&count1==0 && count3>=1 &&count4>=1){
            score+=3;
        }else if(count1==1&&count2==1 && count3>=1 &&count4>=1){
            score+=5;
        }
     
        if(score>=90){
            System.out.print("VERY_SECURE");
        }else if(score>=80){
            System.out.print("SECURE");
        }else if(score>=70){
            System.out.print("VERY_STRONG");
        }else if(score>=60){
            System.out.print("STRONG");
        }else if(score>=50){
            System.out.print("AVERAGE");
        }else if(score>=25){
            System.out.print("WEAK");
        }else if(score>=0){
            System.out.print("VERY_WEAK");
        }
    }
}

这道题就是对字符的练习,我们需要重点了解ASSIC的运用,A~Z的assic是65->90,a->z的assic是97->122,数字的assic可以直接运算,其他的值都是符号

🍊题目九:最近公共祖先

链接

https://www.nowcoder.com/practice/70e00e490b454006976c1fdf47f155d9?tpId=8&&tqId=11017&rp=1&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking

题目解析

最近公共祖先表示距离两个节点最近的公共父节点,这道题考察二叉树

解题思路

题目所描述的满二叉树如下: 1 / \ 2 3 / \ / \ 4 5 6 7 上述树中子节点与父节点之间的关系为root =child / 2 所以如果a != b,就让其中的较大数除以2, 如此循环直到a == b 即是原来两个数的最近公共祖先 比如: 2和7的最近公共祖先:7/2 = 3 —> 3/2 = 1, 2/2 = 1, 得到1为它们的公共祖

代码实现

import java.util.*;

public class LCA {

    public int getLCA(int a, int b) {
        // write code here
        while (a != b) {
            int tmp = 0;
            if (a < b) {
                tmp = b;
                b = a;
                a = tmp;
            }
            a = a/2;
        }
        return a;
    }
}

如果代码看不明白,可以自己画一个完全二叉树,将代码代入即可

🍈题目十:求最大连续bit数

链接

https://www.nowcoder.com/practice/4b1658fd8ffb4217bc3b7e85a38cfaf2?tpId=37&&tqId=21309&rp=1&ru=/activity/oj&qru=/ta/huawei/question-ranking

题目解析

这道题考察位运算

解题思路

根据位运算,获取每一位的二进制值。获取第i位的值: (n >> i) & 1。如果1连续,则计数累加,如果不连续,则从0开始计数。

代码实现

import java.util.*;
public class Main {
    public static void main(String[]args) {
        Scanner scanner = new Scanner(System.in);
        int a = scanner.nextInt();
        int sum = 0;
        int midsum = 1;
        while(a!=0){
            if((a&1)==1){
                sum++;
                midsum = Math.max(sum,midsum);
            }else{
                    sum =0;
            }
            a>>=1;
        }
        System.out.print(midsum);
    }
}

这段代码我们需要注意midsum和sum是如何变化的,这和我们之前的最大子数组和有着异曲同工之妙,这个midsum的值只要不大于1,设置为多少都可以

🍇题目十一:二进制插入

链接

https://www.nowcoder.com/practice/30c1674ad5694b3f8f0bc2de6f005490?tpId=8&&tqId=11019&rp=1&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking

题目解析

本题考察位运算

解题思路

【解题思路】:
i j
n:1024:100000000 00 m:19 : 10011 要把n的二进制值插入m的第j位到第i位,只需要把n先右
移j位,然后再进行或运算(|)即可。

代码实现

🫐题目十二:查找组成一个偶数最接近的两个素数

链接

https://www.nowcoder.com/practice/f8538f9ae3f1484fb137789dec6eedb9?tpId=37&&tqId=21283&rp=1&ru=/activity/oj&qru=/ta/huawei/question-ranking

题目解析

本题题意明确,不做解析

解题思路

本题首先需要判断素数,素数表示除过1和本身,不能被其它数整除。通过循环遍历来判断一个数
是否为素数。最近的两个素数应该从最中间的位置开始向两边查找。

代码实现

import java.util.*;
public class TrueMain12 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int  half = n / 2;
        for (int i = half; i > 0; i++) {
            if (isPrime(i) && isPrime(n - i)) {
                System.out.println(n - i);
                System.out.println(i);
                break;
            }
        }
    }
    public static boolean isPrime(int a) {
        for (int i = 2; i < a; i++) {
            if (a % i == 0) {
                return false;
            }
        }
        return true;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值