zoukankan      html  css  js  c++  java
  • 算法题解之math类题

    Bulb Switcher

    灯泡开关

    思路:除了平方数以外,其他所有位置的灯泡最终都被开关了偶数次,因此最终都为0。问题等价于求1~n中平方数的个数。

    1 public class Solution {
    2     public int bulbSwitch(int n) {
    3         return (int)Math.sqrt(n);
    4     }
    5 }
    View Code

     

    Count Primes

    质数计数

    思路1:暴力法。其中判断每一个数n是不是质数需要验证是否任何小于n的数都不能整除n,这一步是O(n)。因此整体复杂度是O(n^2)。

    思路2:思路1的优化版。如果一个数n不是质数,则n = p * q。令 p <= q,则可以推出 p * p <= n,即 p <= √n。因此思路一中只需要判断是否任何小于等于√n都不能整除n。整体时间复杂度变为O(n^1.5)。

     1 public int countPrimes(int n) {
     2    int count = 0;
     3    for (int i = 1; i < n; i++) {
     4       if (isPrime(i)) count++;
     5    }
     6    return count;
     7 }
     8 
     9 private boolean isPrime(int num) {
    10    if (num <= 1) return false;
    11    // Loop's ending condition is i * i <= num instead of i <= sqrt(num)
    12    // to avoid repeatedly calling an expensive function sqrt().
    13    for (int i = 2; i * i <= num; i++) {
    14       if (num % i == 0) return false;
    15    }
    16    return true;
    17 }
    View Code

    思路3:埃拉托色尼筛选法:对于当前数i(i要从2开始),把它的倍数2i,3i,4i......都标记为不是质数,然后 i 的下一个没有被标记过的数一定是质数。

    优化:(1)如果一个数已经被标记为不是质数了,直接跳过,因为它的倍数之前一定已经标记过了;(2)对于数i,不用从2i开始标记,直接从i * i开始标记(之前的也一定被标记过)。

    算法空间复杂度为O(n),时间复杂度为O(n log log n)。(证明见wiki)

     1 public class Solution {
     2     public int countPrimes(int n) {
     3         boolean[] notPrime = new boolean[n];
     4         int count = 0;
     5         for (int i = 2; i < n; i++) {
     6             if (notPrime[i] == false) {
     7                 count++;
     8                 for (long j = i; i * j < n; j++) {
     9                     notPrime[(int)(i * j)] = true;
    10                 }
    11             }
    12         }
    13         
    14         return count;
    15     }
    16 }
    View Code

    Insert Interval

    插入区间

    思路:区间类题目。先把区间按照start大小插入进去,然后就就跟排好序的merge intervals一样了。

     1 /**
     2  * Definition for an interval.
     3  * public class Interval {
     4  *     int start;
     5  *     int end;
     6  *     Interval() { start = 0; end = 0; }
     7  *     Interval(int s, int e) { start = s; end = e; }
     8  * }
     9  */
    10 public class Solution {
    11     public List<Interval> insert(List<Interval> intervals, Interval newInterval) {
    12         List<Interval> res = new ArrayList<Interval>();
    13         if (intervals == null || intervals.size() == 0) {
    14             res.add(newInterval);
    15             return res;
    16         }
    17         
    18         for (int i = 0; i < intervals.size(); i++) {
    19             if (intervals.get(i).start > newInterval.start) {
    20                 intervals.add(i, newInterval);
    21                 break;
    22             } else if (i == intervals.size() - 1) {
    23                 intervals.add(newInterval);
    24                 break;
    25             }
    26         }
    27         
    28         res.add(intervals.get(0));
    29         for (int i = 1; i < intervals.size(); i++) {
    30             Interval cur = intervals.get(i);
    31             Interval last = res.get(res.size() - 1);
    32             if (cur.start <= last.end) {
    33                 last.end = Math.max(last.end, cur.end);
    34             } else {
    35                 res.add(cur);
    36             }
    37         }
    38         return res;
    39         
    40     }
    41 }
    View Code

    Merge Intervals

    合并区间

    思路:区间类题目。先把所有区间按照start排好序,把第一个区间加到合并集中。然后遍历之后的每个区间,只需要与合并集中最后一个区间进行比较合并。

     1 /**
     2  * Definition for an interval.
     3  * public class Interval {
     4  *     int start;
     5  *     int end;
     6  *     Interval() { start = 0; end = 0; }
     7  *     Interval(int s, int e) { start = s; end = e; }
     8  * }
     9  */
    10 public class Solution {
    11     public List<Interval> merge(List<Interval> intervals) {
    12         
    13         List<Interval> res = new ArrayList<Interval>();
    14 
    15         if (intervals == null || intervals.size() == 0) {
    16             return res;
    17         }
    18         
    19         Comparator<Interval> c = new Comparator<Interval>() {
    20             public int compare(Interval i1, Interval i2) {
    21                 return i1.start - i2.start;
    22             }
    23         };
    24         Collections.sort(intervals, c);
    25         res.add(intervals.get(0));
    26         for (int i = 1; i < intervals.size(); i++) {
    27             Interval cur = intervals.get(i);
    28             Interval last = res.get(res.size() - 1);
    29             if (cur.start <= last.end) {
    30                 last.end = Math.max(last.end, cur.end);
    31             } else {
    32                 res.add(cur);
    33             }
    34         }
    35         return res;
    36     }
    37 }
    View Code

    Power of Three

    判断3的次方

    思路1:循环或者递归。复杂度O(lgn)

    思路2:题目规定不能用loop或者递归。可以调用java的log函数来做。时间仍然是O(lgn)

    思路3:求出int中3的次方的最大值,判断max是否能被n整除。时间是O(1)。power of tow,power of four 均与这题类似。

    public class Solution {
        public boolean isPowerOfThree(int n) {
            int Max3PowerInt = 1162261467;
            if (n > 0 && n <= Max3PowerInt) {
                if (Max3PowerInt % n == 0) {
                    return true;
                }
            }
            return false;
        }
    }
    View Code

    Rectangle Area

    矩形面积

    思路:设矩形1的上下左右边分别为u1,d1,l1,r1,矩形2的上下左右边分别为u2,d2,l2,r2。则两矩形不相交的充要条件是:u1在d2下方 或 u2在d1下方 或 l1在r2右边 或 l2在r1右边。其余情况一定相交。相交面积的求法是:相交矩形的左边是l1和l2其中靠右的边,相交矩形的右边是r1和r2其中靠左的边,相交矩形的上边是u1和u2的靠下的边,相交矩形的下边是d1和d2的靠上的边。

     1 public class Solution {
     2     public int computeArea(int A, int B, int C, int D, int E, int F, int G, int H) {
     3         int area1 = (C - A) * (D - B);
     4         int area2 = (G - E) * (H - F);
     5         if (A >= G || E >= C || B >= H || F >= D) {
     6             return area1 + area2;
     7         }
     8         
     9         int w = Math.min(C, G) - Math.max(A, E);
    10         int h = Math.min(D, H) - Math.max(B, F);
    11         return area1 + area2 - w * h;
    12         
    13     }
    14 }
    View Code
  • 相关阅读:
    第二章 关系模型介绍
    第一章 引言
    只要人人都献出一点爱......
    小算法
    题目:返回一个整数数组中最大子数组的和。
    题目:返回一个整数数组中最大子数组的和
    梦断代码读后感之开始篇
    电梯调度需求分析
    结对开发--求二维数组的最大子数组
    四则运算(3)--答题小系统
  • 原文地址:https://www.cnblogs.com/coldyan/p/6058625.html
Copyright © 2011-2022 走看看