关闭

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

标签: 位运算数学lintcodeleetcode高频
491人阅读 评论(0) 收藏 举报
分类:

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;
        }
    }
}





0
0
查看评论

开源几何计算数学库

a) Geos Geos的全称就是Geometry Engine Open Source,参考网站就是:http://geos.refractions.net,从名称就可以看出,Geos就是判断几何体的过程。 Geos是用C++语言写的处理计算几何的开源库。 b)...
  • dfdfdsfdfdfdf
  • dfdfdsfdfdfdf
  • 2016-08-03 17:49
  • 1827

数学老师必备的一款五星级几何绘图软件!

2016清明小长假刚刚过去,大家似乎还没从假期中走出来,课堂上学生们的那股爱学习的劲好像迟迟没有回归,在这里小编为大家送上一款专业的教学辅助工具,希望能够为老师们的教学增添色彩,提高课堂质量,增加学生的学习兴趣。这款软件就是几何画板,用它可以画出小学到高中的数学几何图,甚至还可以动态演示图形的变换,...
  • BeyondCompareben
  • BeyondCompareben
  • 2016-04-06 16:27
  • 6197

按位运算&数学等价式

按位运算符C++共有6个<< , >> , ~ , & , | , ^移位运算符//左移运算符<<语法: value << shift //value是被操作的整数值,shift是要移动的位数 //功能:左移一位相当于乘2,左移n位相当于乘以...
  • qq_15015129
  • qq_15015129
  • 2016-12-06 17:13
  • 200

高频面试题整理~(持续更新)

高频面试题整理~(持续更新) 1.TCP和UDP的差别: 参考: TCP(Transmission Control Protocol,传输控制协议)是基于连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次“对话”才能建立起来,其中的过程非常复杂,我...
  • huangshulang1234
  • huangshulang1234
  • 2017-11-24 09:17
  • 132

老师必备的数学几何绘图软件,赶紧收藏!

在现代多媒体教学时代,老师如果仅依靠黑板来教学,不仅达不到预期的教学效果,而且对学生的学习帮助不是很大,学生学不好,就容易产生厌学情绪,所以这就需要老师更上时代步伐,采用先进的教学工具来教学,使课堂授课模式多样化,这样才能让学生在学习中感到乐趣。 对于数学老师,更是需要借助教学教具来讲课,比如在学...
  • Xshell_Xmanager
  • Xshell_Xmanager
  • 2017-09-26 13:39
  • 431

《玩不够的数学:算术与几何的妙趣》:第一章 平面上的几何艺术

第一章 平面上的几何艺术 人们往往从悖论中获得思维的乐趣,而几何学的悖论就是不可能图形。如今我们已创造出数千种这样的二维图像,不断挑战我们的眼睛和思维。三角形、披萨饼、七巧板也蕴藏着无穷的变化和巧妙的发现。 不可能!你确信吗? 人们从透视错觉得来灵感,创造了神秘的“不可能图形”。人...
  • GarfieldEr007
  • GarfieldEr007
  • 2016-02-28 16:19
  • 7306

位运算求和

/* * 题目 给出两个整数a和b, 求他们的和, 但不能使用+等数学运算符。 注意事项 你不需要从输入流读入数据,只需要根据aplusb的两个参数a和b,计算他们的和并返回就行。 说明 a和b都是32位整数么? 是的我可以使用位运算符么? 当然可以*/package leetco...
  • qq_17525769
  • qq_17525769
  • 2017-01-04 20:55
  • 502

你所不知道的“位运算及运算过程”

原本今天想和大家谈谈什么是正则表达式的,回来的路上忽然想起位运算,刚好这个知识我也很久没复习了,所以今天和大家一起来复习及学习 那么什么是位运算了?答:就是以二进制运算的一种运算符,下面是今天的内容。   1、& 2、| 3、^ 4、>> ...
  • qq1723205668
  • qq1723205668
  • 2016-06-06 20:58
  • 836

[转]一位MIT计算机博士对数学知识的思考

在过去的一年中,我一直在数学的海洋中游荡,research进展不多,对于数学世界的阅历算是有了一些长进。为什么要深入数学的世界?作为计算机的学生,我没有任何企图要成为一个数学家。我学习数学的目的,是要 想爬上巨人的肩膀,希望站在更高的高度,能把我自己研究的东西看得更深广一些。说起来,我在刚来这个学校...
  • budapest
  • budapest
  • 2013-11-11 09:25
  • 1464

一个超级赖皮的数学证明方法——例证法

今天看到《数学家的眼光》(张景中著)写到了一个巨赖皮的数学证明方法,叫例证法,看完我都惊得不行了,就写到这里来和大家分享一下。 为了说明例证法,我们举一个简单的例子。试证明:(x+1)(x-1)=x^2-1。我们假设我们不会做(这不是在贬低你的智商阿)。现在我就讲一个所有人都肯定能学会的方法,用例...
  • zhaoxiaolon
  • zhaoxiaolon
  • 2013-09-24 17:04
  • 587
    个人资料
    • 访问:18418次
    • 积分:1123
    • 等级:
    • 排名:千里之外
    • 原创:99篇
    • 转载:1篇
    • 译文:0篇
    • 评论:0条