(Java版)剑指offer(二)

13.机器人的运动范围
动态规划
联通性为什么要&& (dp[i - 1][j] || dp[i][j - 1]);

class Solution {
    public int movingCount(int m, int n, int k) {
        //状态:dp[i][j]代表第i,j个格子能否走到
        boolean[][] dp = new boolean[m][n];
        dp[0][0] = isValid(0, 0, k);
        //转移方程
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if(i == 0 && j == 0) continue;
                else if(i == 0) dp[i][j] = isValid(i, j, k) && dp[i][j - 1];//0行边界横向查找
                else if(j == 0) dp[i][j] = isValid(i, j, k) && dp[i - 1][j];//0列边界竖向查找
                else dp[i][j] = isValid(i, j, k) && (dp[i - 1][j] || dp[i][j - 1]);//考虑连通性
            }
        }
        int count = 0;//计算true的个数
        for (boolean[] row : dp) {
            for (boolean ele : row) {
                if (ele) {
                    count++;
                }
            }
        }
        return count;
    }
     public boolean isValid(int i, int j, int k) {
        int sum = 0;
        while (i != 0) {
            sum += i % 10;
            i /= 10;
        }
        while (j != 0) {
            sum += j % 10;
            j /= 10;
        }
        return sum <= k;
    }
}

14-I 剪绳子
数学问题,类比斐波拉契数列

class Solution {
    public int cuttingRope(int n) {
        if(n <= 3) return n - 1;
        int a = n / 3, b = n % 3;
        if(b == 0) return (int)Math.pow(3, a);
        if(b == 1) return (int)Math.pow(3, a - 1) * 4;
        return (int)Math.pow(3, a) * 2;
    }
}

14-II剪绳子,考虑大数取模问题

class Solution {
    public int cuttingRope(int n) {
//有大数取模问题
        if(n <= 3) return n - 1;
        int b = n % 3, p = 1000000007;
        long rem =1,x=3;
        for(int a = n / 3 - 1; a > 0; a /= 2) {
            if(a % 2 == 1) rem = (rem * x) % p;
            x = (x * x) % p;
        }
        if(b == 0) return (int)(rem * 3 % p);
        if(b == 1) return (int)(rem * 4 % p);
        return (int)(rem * 6 % p);//等价于3^(a-1)*3*2
    }
}

15,二进制中1的个数

和>>>的区别
1、>> 表示右移,如果该数为正,则高位补0,若为负数,则高位补1。如:int i=15; i>>2的结果是3,移出的部分将被抛弃。

2、>>>表示无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0。

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
      int res = 0;
      while(n!=0){
          res += n&1;
          n >>>= 1; //表示无符号右移
      }  
      return res;
    }
}

16.数值的整数次方

class Solution {
    public double myPow(double x, int n) {
        if(x == 0) return 0;
        double p=1.0 ;
        long  k = n;
        if(k<0){
            x = 1 / x;
            k =-k;
        }    
        while(k>0){
            if((k & 1) == 1) p *=x;
            x *=x;
            k >>=1;                
        }
        return p;
    }
}

17.打印从1到最大的n位数
若n比较大,则比较耗内存

class Solution {
    public int[] printNumbers(int n) {
        int end = (int)Math.pow(10, n) - 1;
        int[] res = new int[end];
        for(int i = 0; i < end; i++)
            res[i] = i + 1;
        return res  ;    
    }
}

18.删除链表的节点
直接遍历

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode deleteNode(ListNode head, int val) {
        ListNode pre = head;
        ListNode cur  = head.next;
        if(head == null) return null;
        if(head.val == val) return head.next;
        while(cur !=null && cur.val != val){
            //超时
                pre = cur;
                cur = cur.next;                
            }            
        if(cur != null) pre.next = cur.next;//如果找到要删除的节点,节点指向操作
        return head;
    }
}

19,正则表达式匹配
调用match函数可以完成
底层实现有点困难,我还没看懂

20.表示数值的字符串(有难度)
罗列条件,创建查询表

class Solution {
    public boolean isNumber(String s) {
	//key存放类型,value状态
        Map[] states = {
        new HashMap<>() {{ put(' ', 0); put('s', 1); put('d', 2); put('.', 4); }}, // 0.  起始空格 正负号 e 数字.
        new HashMap<>() {{ put('d', 2); put('.', 4); }},                           // 至少一位数字,后面跟着一个点 '.'
        new HashMap<>() {{ put('d', 2); put('.', 3); put('e', 5); put(' ', 8); }}, // 2.  数字.数字e空格
        new HashMap<>() {{ put('d', 3); put('e', 5); put(' ', 8); }},              // 3.
        new HashMap<>() {{ put('d', 3); }},                                        // 4.
        new HashMap<>() {{ put('s', 6); put('d', 7); }},                           // 5.
        new HashMap<>() {{ put('d', 7); }},                                        // 6.
        new HashMap<>() {{ put('d', 7); put(' ', 8); }},                           // 7.
        new HashMap<>() {{ put(' ', 8); }}                                        // 8.若干空格
        };
        int p = 0;
        char t;
        for(char c : s.toCharArray()) {
            if(c >= '0' && c <= '9') t = 'd';
            else if(c == '+' || c == '-') t = 's';
            else if(c == 'e' || c == 'E') t = 'e';
            else if(c == '.' || c == ' ') t = c;
            else t = '?';
            if(!states[p].containsKey(t)) return false;
            p = (int)states[p].get(t);
        }
        return p == 2 || p == 3 || p == 7 || p == 8;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值