[高频] 六.数学,几何计算,位运算常见问题

38. Search a 2D Matrix II: 点击打开链接

 

[
  [1, 3, 5, 7],
  [2, 4, 7, 8],
  [3, 5, 9, 10]
]

 

思路:从第一行最后一个元素(或者第一列最后一个元素)开始遍历,记此元素为x

         如果x<target,砍掉第一行

         如果x>target,砍掉最后一列

         如果x=target,count++,并同时砍掉第一行和最后一列

时间:O(m+n)

 

public class Solution {
    /**
     * @param matrix: A list of lists of integers
     * @param: A number you want to search in the matrix
     * @return: An integer indicate the occurrence of target in the given matrix
     */
    public int searchMatrix(int[][] matrix, int target) {
        if(matrix==null || matrix.length==0){
            return 0;
        }
       
        int row=0;
        int col=matrix[0].length-1;
        int count=0;
        while(row<=matrix.length-1 && col>=0){
            if(target==matrix[row][col]){
                count++;
                row++;
                col--;
            }else if(target>matrix[row][col]){
                row++;
            }else{
                col--;
            }
        }
        return count;
    }
}

161. Rotate Image: 点击打开链接

思路:顺时针90==两次翻转,同理可以推逆时针90

 

1  2  3             
4  5  6
7  8  9
1  4  7                  swap(matrix[i][j],matrix[j][i])
2  5  8
3  6  9
7  4  1                  swap(matrix[i][j],matrix[i][matrix[0].length-1-j])
8  5  2
9  6  3

注意:do it in-place

public class Solution {
    /**
     * @param matrix: A list of lists of integers
     * @return: Void
     */
    public void rotate(int[][] matrix) {
        for(int i = 0; i<matrix.length; i++){
            for(int j = i; j<matrix[0].length; j++){
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        }
        for(int i =0 ; i<matrix.length; i++){
            for(int j = 0; j<matrix[0].length/2; j++){
                int temp = matrix[i][j];
                matrix[i][j] = matrix[i][matrix[0].length-1-j];
                matrix[i][matrix[0].length-1-j] = temp;
            }
        }
    }
}

654. Sparse Matrix Multiplication: 点击打开链接

 

     |  1 0 0 |   | 7 0 0 |   |  7 0 0 |                      7=1*7+0*0+0*0
AB = | -1 0 3 | x | 0 0 0 | = | -7 0 3 |
                  | 0 0 1 |

 

思路:矩阵乘法:C[i][j]=A[i][k]*B[k][j] (如上例子,i=3,k=3,j=3)

时间:O(nmk)

方法一

 

public class Solution {
    /**
     * @param A a sparse matrix
     * @param B a sparse matrix
     * @return the result of A * B
     */
    public int[][] multiply(int[][] A, int[][] B) {
        int[][] result=new int[A.length][B[0].length];
        for(int i=0;i<A.length;i++){
            for(int j=0;j<B[0].length;j++){
                for(int k=0;k<A[0].length;k++){
                    result[i][j]+=A[i][k]*B[k][j];
                }
            }
        }
        return result;
    }
}

方法二

思路:由于是sparse,是稀疏矩阵,有好多0,因此要用上这一条件,但是怎么用时间上还是O(n^3)

public class Solution {
    /**
     * @param A a sparse matrix
     * @param B a sparse matrix
     * @return the result of A * B
     */
    public int[][] multiply(int[][] A, int[][] B) {
        int[][] result=new int[A.length][B[0].length];
        for(int i=0;i<A.length;i++){
            for(int k=0;k<A[0].length;k++){
                if(A[i][k]==0){                                    //如果这边为0
                    continue;
                }
                for(int j=0;j<B[0].length;j++){   
                    result[i][j]+=A[i][k]*B[k][j];                 //这里的result也是0,因此A[i][k]=0时,continue
                }
            }
            
        }
        return result;
    }
}
public class Solution {
    /**
     * @param A a sparse matrix
     * @param B a sparse matrix
     * @return the result of A * B
     */
    public int[][] multiply(int[][] A, int[][] B) {               //除了A[i][k]之外,B[k][j]也要取非零,又优化了一部分
        int[][] result=new int[A.length][B[0].length];
        for(int i=0;i<A.length;i++){
            for(int k=0;k<A[0].length;k++){
                if(A[i][k]!=0){
                    for(int j=0;j<B[0].length;j++){
                        if(B[k][j]!=0){
                            result[i][j]+=A[i][k]*B[k][j];
                        }
                    }
                }
                
            }
        }
        return result;
    }
}

186. Max Points on a Line:   点击打开链接

思路:拿到当前点和下一点,先判断是不是相同点,如果是,duplicate++,看下一点的下一点与当前点的关系

         如果不是相同点,判断是不是垂直线(垂直线无法这样算斜率),如果是,vertical++,

         如果不是垂直线,再在map里进行统计

 

/**
 * Definition for a point.
 * class Point {
 *     int x;
 *     int y;
 *     Point() { x = 0; y = 0; }
 *     Point(int a, int b) { x = a; y = b; }
 * }
 */
public class Solution {
    /**
     * @param points an array of point
     * @return an integer
     */
    public int maxPoints(Point[] points) {
        if(points==null || points.length == 0) {
            return 0;
        }
        if(points.length <= 2){
            return points.length;
        } 
        int maxVal = Integer.MIN_VALUE;
        for(int i = 0; i < points.length-1; i++){
            HashMap<Double, Integer> map = new HashMap<Double, Integer>();
            int vertical=1;
            int duplicate = 0;
            int currMax = 0;
            for(int j = i + 1; j < points.length; j++){             //for循环j里的每一点都要和当前点i比较
                if(points[i].x == points[j].x && points[i].y == points[j].y){
                    duplicate++;
                    continue;
                }
                if(points[i].x == points[j].x){
                    vertical++;
                    continue;
                }
                double k=(double)(points[i].y-points[j].y)/(double)(points[i].x-points[j].x);
                if(!map.containsKey(k)){
                    map.put(k,2);
                }else{
                    map.put(k,map.get(k)+1);
                }
                currMax = Math.max(currMax, map.get(k));            //经过map统计,得到普通共线最大值
            }
            currMax = Math.max(vertical, currMax) + duplicate;      //经过该点i的普通线和垂直线那种多,再加上该点的相同点
            maxVal = Math.max(currMax, maxVal);                     //由于maxVal定义的位置,因此还得加上这句
        }
        return maxVal;
    }
}

655. Big Integer Addition:  点击打开链接

public class Solution {
    /**
     * @param num1 a non-negative integers
     * @param num2 a non-negative integers
     * @return return sum of num1 and num2
     */
    public String addStrings(String num1, String num2) {
        int diff=Math.abs(num1.length()-num2.length());
      
        if(num1.length()>num2.length()){                                 //先把长度短的前面用0补齐
            for(int i=0;i<diff;i++){
                num2="0"+num2;
            }
        }else{
            for(int i=0;i<diff;i++){
                num1="0"+num1;
            }
        }
        
        String result="";                                               //然后"模十除十"
        int carry=0;
        for(int i=num1.length()-1;i>=0;i--){
            int sum=carry+(num1.charAt(i)-'0')+(num2.charAt(i)-'0');
            int digit=sum%10;
            result+=digit;
            carry=sum/10;
        }
        
        if(carry!=0){                                                   //最后一位如果有carry,直接加到result串上
            result+=carry;
        }
        return new StringBuffer(result).reverse().toString();
    }
}

408. Add Binary:  点击打开链接

public class Solution {
    /**
     * @param a a number
     * @param b a number
     * @return the result
     */
    public String addBinary(String a, String b) {
        int diff=Math.abs(a.length()-b.length());
        if(a.length()>b.length()){
            for(int i=0;i<diff;i++){
                b="0"+b;
            }
        }else{
            for(int i=0;i<diff;i++){
                a="0"+a;
            }
        }
        
        String result="";
        int carry=0;                                                    //和上题一样,只不过是二进制,"模二除二"
        for(int i=a.length()-1;i>=0;i--){                               
            int sum=carry+(a.charAt(i)-'0')+(b.charAt(i)-'0');
            int digit=sum%2;
            result+=digit;
            carry=sum/2;
        }
        if(carry!=0){
           result+=carry; 
        }
        return new StringBuffer(result).reverse().toString();
    }
}

167. Add Two Numbers:  点击打开链接

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;      
 *     }
 * }
 */
public class Solution {
    /**
     * @param l1: the first list
     * @param l2: the second list
     * @return: the sum list of l1 and l2 
     */
    public ListNode addLists(ListNode l1, ListNode l2) {
        if(l1==null && l2==null){
            return null;
        }
        
        ListNode dummy=new ListNode(-1);
        ListNode head=dummy;
        int carry=0;
        while(l1!=null && l2!=null){
            int sum=carry+l1.val+l2.val;
            head.next=new ListNode(sum%10);
            carry=sum/10;
            l1=l1.next;
            l2=l2.next;
            head=head.next;
        }
        while(l1!=null){
            int sum=carry+l1.val;
            head.next=new ListNode(sum%10);
            carry=sum/10;
            l1=l1.next;
            head=head.next;
        }
        while(l2!=null){
            int sum=carry+l2.val;
            head.next=new ListNode(sum%10);
            carry=sum/10;
            l2=l2.next;
            head=head.next;
        }
        
        if(carry!=0){
            head.next=new ListNode(carry);
        }
        return dummy.next;
    }
}

656. Big Integer Multiplication:   点击打开链接

思路:pos[i+j+1]+=product这个时候pos[i+j+1]位置上的数是实际的数字,很可能大于10

         pos[k]=digit这个时候pos[k]位置上的数是最后要放的那一位数,一定小于10

 

public class Solution {
    public String multiply(String num1, String num2) {
        int[] pos=new int[num1.length()+num2.length()];                 //最大长度是num1.length()+num2.length()
        for(int i=num1.length()-1;i>=0;i--){
            for(int j=num2.length()-1;j>=0;j--){
                int product=(num1.charAt(i)-'0')*(num2.charAt(j)-'0');
                pos[i+j+1]+=product;                                    //以45和123为例
            }
        }                                                               //for循环结束int[] pos={0,4,13,22,15}
        
        int carry=0;
        StringBuffer sb=new StringBuffer();
        for(int k=pos.length-1;k>=0;k--){
            int digit=(pos[k]+carry)%10;
            carry=(pos[k]+carry)/10;
            pos[k]=digit;
            sb.insert(0,digit);                                         //每次都放到到索引0位置
        }
    
        
        while(sb.length()>0 && sb.charAt(0)=='0'){                      //trim前导零,有两种情况:
            sb.deleteCharAt(0);                                         //第一位是0,没有用满最大长度
        }                                                               //或者最终乘积为0,例如999*0,不能输出"000"
        return sb.length()==0?"0":sb.toString();       
    }
}

428. Pow(x,n):  点击打开链接

思路:二分法

public class Solution {
    /**
     * @param x the base number
     * @param n the power number
     * @return the result
     */
    public double myPow(double x, int n) {
        if(n==0){
            return 1;
        }
        
        if(n<0){
           x=1/x;
           n=-n;
        }
        
        double v=myPow(x,n/2);
        if(n%2==0){                                    //用n%2的好处是结果只有0或是1两种情况
            return v*v;
        }else{
            return v*v*x;
        }
    }
}

2019/05/31补充Bit Manipulation: 

最近做OA有感,觉得Bit太好用, 真是活生生用O(n)就可以解决一些题。

转一讲解很详细Bit原理的帖子: https://www.jianshu.com/p/25ddeb1d9adf

338. Counting Bits

class Solution {
    public int[] countBits(int num) {        
        int[] results = new int[num+1];        
        if(num ==0)
        {
            results[0] = 0;
        }
        
        for(int i=0; i<=num; i++)
        {
            int countOne=0;
            int cur=i;
            while(cur>0)           // 没啥难度,知道十进制转化二进制原理,自然就解出来                    
            {                      // 但是按Leetcode的提交统计,performance相对于DP还是差一些
                if(cur%2 == 1)
                {
                    countOne++;
                }                
                cur = cur/2;               
            }    
            results[i]= countOne;
        }        
        return results;
    }
}

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值