• 30天刷题计划(五)


    加油鸭 

    目录

    1.另类加法

    2.求路径总数

    3.井字棋

    4.密码等级强度


    1.另类加法

    另类加法_牛客题霸_牛客网 (nowcoder.com)icon-default.png?t=M666https://www.nowcoder.com/practice/e7e0d226f1e84ba7ab8b28efc6e1aebc?tpId=8&&tqId=11065&rp=1&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking

    ①题目及示例:

     ②方法及解析:

    因为题目中明确指出不得使用+和其他的算术运算符。所以,我们很容易想到位运算符。

    在利用位运算符的时候,我们又该用哪种位运算符呢?

    首先我们得知道,我们会遇到进位和不进位两种情况。比如:1+2=3就不用进位(用二进制来看),3+2=5就需要进位。如果不需要进位,那么我们直接用异或运算即可。如果需要进位,我们就需要知道如何才能进位,这个时候我们就得先进行按位与运算,然后将结果进行左移一位。所以,我们无非进行下面两个操作。

    a.判断是否需要进位:(&运算符,因为全1为1,有0为0,若全为0,则表示不需要进位,因为是二进制,满二进一)

    b.将异或后的结果与进位左移的结果的值进行相加(此处仍然用的是异或)

    c.将b中的两值重复a,b步骤,直到不需要进位为止

    实质上:位运算A^B是不考虑进位的结果,(A&B)<<1是求得的进位

    因此A^B+(A&B)<<1的结果就是和,只要(A&B)<<1=0,两项就变成了一项,不需要加法了

    代码如下:

    1. import java.util.*;
    2. public class UnusualAdd {
    3. public int addAB(int A, int B) {
    4. // write code here
    5. if(B==0){
    6. return A;
    7. }
    8. int tmp;
    9. int sum;
    10. while(B!=0){
    11. sum=A^B;//求两个数的和,不进位的那种
    12. tmp=(A&B)<<1;//判断是否需要进位
    13. A=sum;
    14. B=tmp;
    15. }
    16. return A;
    17. }
    18. }

    2.求路径总数

    走方格的方案数_牛客题霸_牛客网 (nowcoder.com)icon-default.png?t=M666https://www.nowcoder.com/practice/e2a22f0305eb4f2f9846e7d644dba09b?tpId=37&&tqId=21314&rp=1&ru=/activity/oj&qru=/ta/huawei/question-ranking

    ①题目及示例:

     ②方法及解析:

    a.递归方法来做:

    这道题之前刷过,是按照递归的思想来进行操作的,大家可以看看下面这个图。

    代码如下:

    1. import java.util.*;
    2. public class Main {
    3. public static int load(int m,int n){
    4. if((m==1&&n>=1)||(n==1&&m>=1)){
    5. return m+n;
    6. }
    7. return load(m-1,n)+load(m,n-1);
    8. }
    9. public static void main(String[] args) {
    10. Scanner sc=new Scanner(System.in);
    11. int n=sc.nextInt();
    12. int m=sc.nextInt();
    13. System.out.println(load(m,n));
    14. }
    15. }

     b.动态规划来做:

    首先我们应该了解一下动态规划的相关思路:

    动态规划实际和递归在原理上是非常像的,都是通过以前数学中的归纳法来着手。通俗一点来说,就是这一步是由上一步推导得来,而上一步又是以同样的规律由上上步得来,然后依次类推的过程。

    而在动态规划中我们常用到的步骤往往是:

    1.确定状态(两个核心:1最后一步  2化成子问题)

    2.转移方程

    3.开始和边界条件

    以下面这个题为例,我们来做一个剖析:

    62. 不同路径 - 力扣(LeetCode)icon-default.png?t=M666https://leetcode.cn/problems/unique-paths/

    我们的最终目的是让五角星走到圆圈处。(3行,4列)

    (1)确定状态:

    状态:设f[m][n]为机器人有多少种方式从左上角走到(m, n)

    很显然,最后一步要么是[1][3]向下,要么是[2][2]向右

     

    要是有m行,n列放在这种二维数组中,我们就可以发现,要到达的圆圈[m-1][n-1];那么最后的两种结果无非是:[m-2][n-1]和[m-1][n-2];

    所以我们就进而转化成了子问题:

    就是将上述两种结果,分别再分析,发现还是得到同样的关系。

    到[m-2][n-1]的方式无非是:[m-3][n-1]和[m-2][n-2]。其它的以此类推。

    (2)我们就可以确定状态方程为:对于任意一个格子(m, n)有:

      f[m][n] = f[m-1][n] + f[m][n-1];

    (3)开始和边界条件:

    若是m,n均为0,那么此时走到这个位置的方式只有1中;因为就是其本身。

    若是只有行m,那么结果就是走到(m-1,0);这个时候只能向右走,只有一种方式。

    即:f[m][n] = 1

    同理,若只有列n,那么结果就是走到(0,n-1);这个时候只能向下走,也只有一种方式。

    即:f[m][n] = 1

    代码如下:

    1. import java.util.Scanner;
    2. class Main {
    3. public static void main(String[] args) {
    4. Scanner in = new Scanner(System.in);
    5. int a = in.nextInt();
    6. int b = in.nextInt();
    7. System.out.println(work(a,b));
    8. }
    9. private static int work(int n, int m) {
    10. int[][] dp = new int[n][m];
    11. // 只有1列
    12. for (int i = 0; i
    13. dp[i][0] = 1;
    14. }//只有1行
    15. for (int j = 0; j
    16. dp[0][j] = 1;
    17. }
    18. // 递推
    19. for (int i = 1;i < n;i++){
    20. for(int j = 1;j< m ;j++){
    21. dp[i][j] = dp[i][j-1]+dp[i-1][j];
    22. }
    23. }
    24. return dp[n-1][m-1];
    25. }
    26. }

    但是本题是从左上顶点走到右下顶点,所以这里的数组横纵坐标均要+1;

    代码如下:

    1. import java.util.Scanner;
    2. public class Main {
    3. public static void main(String[] args) {
    4. Scanner in = new Scanner(System.in);
    5. int a = in.nextInt();
    6. int b = in.nextInt();
    7. System.out.println(work(a,b));
    8. }
    9. private static int work(int n, int m) {
    10. // 定义二位dp数组dp[i,j] = dp[i-1,j]+dp[i,j-1];
    11. //因为对于n个格子来说,有n+1个顶点
    12. int[][] dp = new int[n + 1][m + 1];
    13. // 只有1列
    14. for (int i = 0; i <= n; i++) {
    15. dp[i][0] = 1;
    16. }//只有1行
    17. for (int j = 0; j <= m; j++) {
    18. dp[0][j] = 1;
    19. }
    20. // 递推
    21. for (int i = 1;i <= n;i++){
    22. for(int j = 1;j<= m ;j++){
    23. dp[i][j] = dp[i][j-1]+dp[i-1][j];
    24. }
    25. }
    26. return dp[n][m];
    27. }
    28. }

    3.井字棋

    井字棋_牛客题霸_牛客网 (nowcoder.com)icon-default.png?t=M666https://www.nowcoder.com/practice/e1bb714eb9924188a0d5a6df2216a3d1?tpId=8&&tqId=11055&rp=1&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking

    ①题目及示例:

     

    ②方法及解析:

    这个题很简单,实际上只需要我们保证横排,纵列,主对角线和副对角线的数,这其中有一种全为1,那么则输出true。代码如下:

    特别需要注意一下的是每行或每列计算结束后要将sum置为0,否则还是会进行累加,而导致结果不准确。

    1. import java.util.*;
    2. class Main{
    3. public static boolean checkWon(int[][] board) {
    4. // write code here
    5. int sum=0;
    6. //对行
    7. for(int i=0;i0].length;i++){
    8. sum=0;
    9. for(int j=0;j
    10. sum+=board[i][j];
    11. if(sum==board.length){
    12. return true;
    13. }
    14. }
    15. }//对列
    16. for(int i=0;i0].length;i++){
    17. sum=0;
    18. for(int j=0;j
    19. sum+=board[j][i];
    20. if(sum==board.length){
    21. return true;
    22. }
    23. }
    24. }sum=0;
    25. //主对角线
    26. for(int i=0;i
    27. sum+=board[i][i];
    28. if(sum==board.length){
    29. return true;
    30. }
    31. }sum=0;
    32. //副对角线
    33. for(int i=0;i
    34. sum+=board[i][board.length-1-i];
    35. if(sum==board.length){
    36. return true;
    37. }
    38. }
    39. return false;
    40. }
    41. public static void main(String[]args){
    42. Scanner sc=new Scanner(System.in);
    43. int[][]array={{-1,1,-1},{0,0,1},{0,0,0}};
    44. boolean flg=checkWon(array);
    45. System.out.println(flg);
    46. }
    47. }

    4.密码等级强度

    密码强度等级_牛客题霸_牛客网 (nowcoder.com)icon-default.png?t=M666https://www.nowcoder.com/practice/52d382c2a7164767bca2064c1c9d5361?tpId=37&&tqId=21310&rp=1&ru=/activity/oj&qru=/ta/huawei/question-ranking

    ①题目及示例:

     ②方法及解析:

    这个就是罗列出来,直接上代码:

    1. import java.util.*;
    2. public class Main {
    3. public static void main(String[] args){
    4. Scanner sc=new Scanner(System.in);
    5. while(sc.hasNextLine()){
    6. String str=sc.nextLine();
    7. int sum1=getLen(str);
    8. int sum2=getChar(str);
    9. int sum3=getNum(str);
    10. int sum4=getSym(str);
    11. int sum=0;
    12. if(sum2==20&&sum3>=1&&sum4>=1){
    13. sum=sum1+sum2+sum3+sum4+5;
    14. }else if(sum2==10&&sum3>=1&&sum4>=1){
    15. sum=sum1+sum2+sum3+sum4+3;
    16. }else if(sum2==10&&sum3>=1&&sum4==0){
    17. sum=sum1+sum2+sum3+sum4+2;
    18. }else{
    19. sum=sum1+sum2+sum3+sum4;
    20. }if(sum>=90){
    21. System.out.println("VERY_SECURE");
    22. }else if(sum>=80){
    23. System.out.println("SECURE");
    24. }else if(sum>=70){
    25. System.out.println("VERY_STRONG");
    26. }else if(sum>=60){
    27. System.out.println("STRONG");
    28. }else if(sum>=50){
    29. System.out.println("AVERAGE");
    30. }else if(sum>=25){
    31. System.out.println("WEAK");
    32. }else if(sum>=0){
    33. System.out.println("VERY_WEAK");
    34. }
    35. }
    36. }public static int getLen(String str){
    37. if(str.length()<=4){
    38. return 5;
    39. }else if(7>=str.length()&&str.length()>=5){
    40. return 10;
    41. }else if(str.length()>=8){
    42. return 25;
    43. }return 0;
    44. }public static int getChar(String str){
    45. int small=0; int big=0; for(int i=0;iif(str.charAt(i)>=65&&str.charAt(i)<=90){
    46. big++;
    47. }else if(str.charAt(i)>=97&&str.charAt(i)<=122){
    48. small++;
    49. }
    50. }if(small>0&&big>0){
    51. return 20;
    52. }else if(small>0||big>0){
    53. return 10;
    54. }else{
    55. return 0;
    56. }
    57. }public static int getNum(String str){
    58. int num=0;
    59. for(int i=0;i
    60. if(str.charAt(i)-'0'>=0 && str.charAt(i)-'0'<=9){
    61. num++;
    62. }
    63. }if(num>1){
    64. return 20;
    65. }else if(num==1){
    66. return 10;
    67. }else{
    68. return 0;
    69. }
    70. }public static int getSym(String str){
    71. int num=0;
    72. for(int i=0;i
    73. 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)-'0'<=9)){
    74. num++;
    75. }
    76. }if(num>1){
    77. return 25;
    78. }else if(num==1){
    79. return 10;
    80. }else{
    81. return 0;
    82. }
    83. }
    84. }
  • 相关阅读:
    刨根问底:为什么玩游戏会让手机变得更热?
    [每周一更]-(第64期):Dockerfile构造php定制化镜像
    apk反编译修改教程系列-----修改apk中的图片 任意更换apk桌面图片【三】
    Seata 源码篇之AT模式启动流程 - 上 - 02
    Yew应用中如何获取<textarea/>的值?
    Java——》乐观锁、悲观锁
    tail -f 与 tailf 的区别
    3D项目中用到的一些算法
    Activiti回退与跳转节点
    23、Android -- OKHttp3 基础学习
  • 原文地址:https://blog.csdn.net/weixin_58850105/article/details/126048750