三月一日offer_10,15,17,18and两个练习

剑指 Offer 10- II. 青蛙跳台阶问题

青蛙跳台问题,最开始的想法就是递归方法,但是是超时的

class Solution {
    public int numWays(int n) {
        if(n==1||n ==0){
            return 1;
        } else if (n == 2) {
            return 2;
        } else {
            return (numWays(n - 1) + numWays(n - 2))%1000000007;
        }
    }
}

第二种就是循环求余法,有(a+b)%p = (a%p+b%p)%p的规则,所以也是一种递归的思路来解决。(有动态规划法,二刷※)

class Solution {
    public int numWays(int n) {
        int a = 1, b = 1, sum;
        for(int i = 0; i < n; i++){
            sum = (a + b) % 1000000007;
            a = b;
            b = sum;
        }
        return a;
    }
}
剑指 Offer 15. 二进制中1的个数

本题主要是考的对于运算符的理解和使用,做起来挺绕的,而且也是第一个做相应的题型。

第一种的思路是((n&(1<<i))!=0),用n和n的相应位置为1时做与运算,如果是1,结果不为0,1的个数加一。

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int ret = 0;
        for(int i=0;i<32;i++){
            if ((n & (1 << i)) != 0) 
                ret++;
            }
        }
        return ret;
    }
}

还有很多的方法来解决,比如用tar += n&1 n>>>1;每次tar加0或1,然后n右移一位。和上面的类似,一个是1动,一个是1不动。

public class Solution {
    public int hammingWeight(int n) {
        int res = 0;
        while(n != 0) {
            res += n & 1;
            n >>>= 1;
        }
        return res;
    }
}

第三种当时也是想了很久,核心为 while(n != 0) { res++; n &= n - 1; },n不为0,即n包含1,先加,然后n&=n-1,就是每次把最后一个1消掉,当时就是这一点,忽略了那个等于好,直接犯傻了。每种思路都会让我醒悟,也确实学到了!

public class Solution {
    public int hammingWeight(int n) {
        int res = 0;
        while(n != 0) {
            res++;
            n &= n - 1;
        }
        return res;
    }
}
剑指 Offer 17. 打印从1到最大的n位数

又是到了能用到暴力法的了,只能说难题我畏畏缩缩,只会cv,简单题我必重拳出击。

先一个循环把需要打印的数范围扩大到10^n。然后就是最喜欢的依次遍历了插入了。

class Solution {
    public int[] printNumbers(int n) {
        int t = 1;
        for(int i = 0;i<n;i++){
            t *= 10;
        }
        int[] a = new int[t-1];
        for(int i=1;i<t;i++){
            a[i-1] = i;
        }
        return a;
        }
    }

然后对于次方的计算,也是有相对的函数的,显然这样看起来比较简洁。

int end = (int)Math.pow(10, n) - 1;

这一题也就是一个全排列问题,但是还没有一点思路。

剑指 Offer 18. 删除链表的节点

感觉有段时间没有刷到链表题了,这一题也就是基本的链表的删除,只要注意特殊情况,并且在找到删除值的时候,让其前一个的next指向其本身的next即可。(单指针)

class Solution {
    public ListNode deleteNode(ListNode head, int val) {
            if(head == null){
                return null;
            }
            if(head.val == val){
                return head.next;
            }
            ListNode cur = head;
            while(cur.next != null && cur.next.val != val){
                cur = cur.next;
            }
            if(cur.next!=null){  //这一处是判断cur.next不为空,就是找到要删除的节点,
                                 //但是本题来说,不是必要,因为删除结点存在。
                cur.next = cur.next.next;
            }
        
            return head;
    }

(双指针)相对于单个指针,更好去看明白删除的过程。

class Solution {
    public ListNode deleteNode(ListNode head, int val) {
            if(head == null){
                return null;
            }
            if(head.val == val){
                return head.next;
            }
            ListNode pre = head, cur = head.next;
            while(cur != null && cur.val != val){
                pre = cur;
                cur = cur.next;
            }
            if(cur!=null){
                pre.next = cur.next;
            }
            else{
                
            }
            return head;
    }
}
if(cur!=null)

其实对于这句话,我刚开始是不理解的,我一直在想,上面的while已经判断过了,那肯定就是找到了val,然后我改成了cur.next!=null;但是忽略了如果找到的元素在最后,那就无解了,也是困扰了挺久,最后所幸理解透了。

566. 重塑矩阵

再怎么重塑矩阵,首先他的m*n是永远等于新的长度r*c的。第一种想法,显然是双重循环输出新数组,而对其判定就是先对其列增加,当达到原矩阵列的长度时,置0,行增加。

class Solution {
    public int[][] matrixReshape(int[][] mat, int r, int c) {
        int m = mat.length;
        int n = mat[0].length;
        if(m * n != r * c){
            return mat;
        }
            int[][] a = new int[r][c];
            int x = 0;
            int y = 0;
            for(int i = 0;i<r;i++)
            {
                for(int j = 0;j<c;j++){
                    a[i][j] = mat[x][y];
                    y++;
                    if(y>=n){
                        y=0;
                        x++;
                    }
                }
            }
        return a;
    }
}

第二种的输出就很巧妙,是一种映射的方法,做除运算和余运算来更新数组坐标。

class Solution {
    public int[][] matrixReshape(int[][] mat, int r, int c) {
        int m = mat.length;
        int n = mat[0].length;
        if(m * n != r * c){
            return mat;
        }
            int[][] ans = new int[r][c];
            
            for(int i = 0;i<m*n;i++)
            {
              ans[i / c][i % c] = mat[i / n][i % n];
            }
        return ans;
    }
}

正巧还看到一个哈希表的方法,便自己模仿着写了一遍,对于哈希表的使用也算是熟悉了的,就是有点不大明白为啥空间和时间变化挺大的。

class Solution {
    public int[][] matrixReshape(int[][] mat, int r, int c) {
        int m = mat.length;
        int n = mat[0].length;
        int t = 0;
        if(m * n != r * c){
            return mat;
        }
        Map<Integer,Integer> map = new HashMap<>();
        for(int i = 0;i < m; i++)
        {
            for(int j = 0;j < n; j++){
                map.put(t++, mat[i][j]);
            }
        }
        int[][] ans = new int[r][c];
        for(int i = 0;i < r;i++)
        {
            for(int j = 0;j < c;j++)
            {
                ans[i][j] = map.get(i*c+j);
            }
        }
        return ans;
    }
}
118. 杨辉三角

杨辉三角问题,其实在大一学c++就接触了,记得当时还是一个考试热门题呢,就是迭代递归问题,求左上角和右上角的和为当前插入的元素值。就是第一次遇到List<List<Integer>>的用法,比二维数组方便多了。

class Solution {
    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> ret = new ArrayList<List<Integer>>();
        for(int i = 0;i<numRows;i++){
            List<Integer> row = new ArrayList<Integer>();
            for(int j = 0;j<=i;j++){
                if(j==0||j==i)
                {
                    row.add(1);
                }
                else
                {
                    row.add(ret.get(i - 1).get(j - 1) + ret.get(i - 1).get(j));
                } 
            }
            ret.add(row);
        }
        return ret;
    }
}

也做了递归法,但是超时了。


class Solution {
    public List<List<Integer>> generate(int numRows)
    {
        List<List<Integer>> ret = new ArrayList<List<Integer>>();
        for (int i = 0; i < numRows; i++) {
            List<Integer> row = new ArrayList<Integer>();
            for (int j = 0; j <=i; j++) {
                row.add(generate_1(i, j));
            }
            ret.add(row);
        }
    return ret;
}

private int generate_1(int i, int j) {
    int result = 0;
    if (j == 0 || j == i) {
        result = 1;
    } 
    else {
        result =(generate_1(i - 1, j - 1) + generate_1(i - 1, j));
    }
    return result;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值