lintcode:1-10题

难度系数排序,容易题1-10题:

Cosine Similarity new 

Fizz Buzz 

O(1)检测2的幂次 

x的平方根 

不同的路径 

不同的路径 II 

两个字符串是变位词 

两个链表的和

中位数

主元素

Cosine Similarity

题目:

Cosine similarity is a measure of similarity between two vectors of an inner product space that measures the cosine of the angle between them. The cosine of 0° is 1, and it is less than 1 for any other angle.

See wiki: Cosine Similarity

Here is the formula:

/media/problem/cosine-similarity.png

Given two vectors A and B with the same size, calculate the cosine similarity.

Return 2.0000 if cosine similarity is invalid (for example A = [0] and B = [0]).

样例

Given A = [1, 2, 3], B = [2, 3 ,4].

Return 0.9926.

Given A = [0], B = [0].

Return 2.0000

解题:

Java程序:

class Solution {
    /**
     * @param A: An integer array.
     * @param B: An integer array.
     * @return: Cosine similarity.
     */
    public double cosineSimilarity(int[] A, int[] B) {
        // write your code here
        int ab = 0;
        double aa = 0.0;
        double bb = 0.0;
        if(A.length != B.length) return 2.0000;
        
        if(A.length==1 && A[0]==0 || B.length==1 && B[0]==0) 
            return 2.0000;
        for(int i=0;i<A.length;i++){
            ab += A[i] * B[i];
            aa += A[i] * A[i];
            bb += B[i] * B[i];
        }
        if(aa==0 || bb==0) return 2.0000;
        aa = Math.sqrt(aa);
        bb = Math.sqrt(bb);
        return ab/(aa*bb);
    }
}
View Code

Python程序:

class Solution:
    """
    @param A: An integer array.
    @param B: An integer array.
    @return: Cosine similarity.
    """
    def cosineSimilarity(self, A, B):
        # write your code here
        ab = 0
        aa = 0
        bb = 0
        if(len(A)!=len(B)) : return 2.0000
        # if len(A)==1 and A[0] = 0 or len(B)==1 and B[0]=0 : return 2.0000;
        for i in range(len(A)):
            ab += A[i]*B[i]
            aa += A[i]*A[i]
            bb += B[i]*B[i]
        if aa==0 or bb==0 : return 2.0000
        aa = aa**0.5
        bb = bb**0.5
        return ab/(aa*bb)
View Code

Fizz Buzz

题目:

给你一个整数n. 从 1 到 n 按照下面的规则打印每个数:

  • 如果这个数被3整除,打印fizz.
  • 如果这个数被5整除,打印buzz.
  • 如果这个数能同时被35整除,打印fizz buzz.
样例

比如 n = 15, 返回一个字符串数组:

["1", "2", "fizz", "4", "buzz", "fizz", "7", "8", "fizz", "buzz", "11", "fizz", "13", "14", "fizz buzz"]

解题:

Java程序:

class Solution {
    /**
     * param n: As description.
     * return: A list of strings.
     */
    public ArrayList<String> fizzBuzz(int n) {
        ArrayList<String> results = new ArrayList<String>();
        for (int i = 1; i <= n; i++) {
            if (i % 15 == 0) {
                results.add("fizz buzz");
            } else if (i % 5 == 0) {
                results.add("buzz");
            } else if (i % 3 == 0) {
                results.add("fizz");
            } else {
                results.add(String.valueOf(i));
            }
        }
        return results;
    }
}
View Code

Python程序:

class Solution:
    """
    @param n: An integer as description
    @return: A list of strings.
    For example, if n = 7, your code should return
        ["1", "2", "fizz", "4", "buzz", "fizz", "7"]
    """
    def fizzBuzz(self, n):
        results = []
        for i in range(1, n+1):
            if i % 15 == 0:
                results.append("fizz buzz")
            elif i % 5 == 0:
                results.append("buzz")
            elif i % 3 == 0:
                results.append("fizz")
            else:
                results.append(str(i))
        return results
View Code

O(1)检测2的幂次

O(1) Check Power of 2

题目:

用 O(1) 时间检测整数 n 是否是 2 的幂次。

样例

n=4,返回 true;

n=5,返回 false.

注意

O(1) 时间复杂度

解题:

Java程序:

class Solution {
    /*
     * @param n: An integer
     * @return: True or false
     */
    public boolean checkPowerOf2(int n) {
        // write your code here
        if(n==1) return true;
        if(n<=0 || n%2==1) return false;
        while(n!=0){
            n=n/2;
            if(n==1) return true;
            if(n%2==1) return false;
        }
        return true;
    }
};
View Code

原来就是利用到奇数不是2的次幂,进行排除

这里的时间复杂度应该是O(log2n) ,在最坏的情况下n就是2的幂次方,while循环要进行到k次,2^k = n

但是这个也AC了

看到下面程序,利用到若n是2的次幂则,n和n-1的二进制表示对应位置都不一样

class Solution {
    /*
     * @param n: An integer
     * @return: True or false
     */
    public boolean checkPowerOf2(int n) {
        // write your code here
        if(n<=0) return false;
        return (n & (n-1)) == 0 ? true : false;
    }
};
View Code

Python程序:

class Solution:
    """
    @param n: An integer
    @return: True or false
    """
    def checkPowerOf2(self, n):
        # write your code here
        if n<=0 : return False
        if n==1 : return True
        if n%2==1 : return False
        while n!=0:
            n/=2
            if n==1 or n==0: return True
            if n%2==1:return False
        return True
View Code

x的平方根

Sqrt(x)

题目:

实现 int sqrt(int x) 函数,计算并返回 x 的平方根。

样例

sqrt(3) = 1

sqrt(4) = 2

sqrt(5) = 2

sqrt(10) = 3

挑战

O(log(x))

解题:

Java程序:

这样也行!!!

class Solution {
    /**
     * @param x: An integer
     * @return: The sqrt of x
     */
    public int sqrt(int x) {
        // write your code here
        return (int)Math.sqrt(x);
    }
}
View Code

下面程序通过45%

class Solution {
    /**
     * @param x: An integer
     * @return: The sqrt of x
     */
    public int sqrt(int x) {
        // write your code here
        // return (int)Math.sqrt(x);
        int n = x/2 + 1;
        int min = n;
        int res = 0;
        for(int i=1;i<=n;++i){
            int tmp = x - i*i;
            if(tmp >=0 && tmp<=min){
                min = tmp;
                res = i;
            }
        }
        return res;
    }
}
View Code

官方答案,利用二分法,寻找离sqrt(x)最近的数

class Solution {
    /**
     * @param x: An integer
     * @return: The sqrt of x
     */
    public int sqrt(int x) {
        // write your code here
        // return (int)Math.sqrt(x);
        int left = 1;
        int right = x/2 + 1;
        int mid;
        int res=1;
        int tmp;
        if (x<2) return x;
        while(left<=right){
           mid = left + (right - left)/2;
            tmp = x/mid;
            if(tmp>mid){
                left = mid + 1;
                res = mid;
            }else if(tmp<mid){
                right = mid - 1;
            }else
                return mid;
        }
        return res;
    }
}
View Code

时间复杂度O(log2x)

Python程序:

class Solution:
    """
    @param x: An integer
    @return: The sqrt of x
    """
    def sqrt(self, x):
        # write your code here
        if x<2 : return x
        left = 1 
        right = x/2 + 1
        res = 0 
        mid = 0
        while left <= right:
            mid = left + (right - left)/2
            tmp = x/mid
            if tmp>mid:
                left = mid + 1
                res = mid
            elif tmp<mid:
                right = mid - 1
            else:
                return mid;
        return res
            
View Code

不同的路径

Unique Paths

题目:

有一个机器人的位于一个M×N个网格左上角(下图中标记为'Start')。

机器人每一时刻只能向下或者向右移动一步。机器人试图达到网格的右下角(下图中标记为'Finish')。
问有多少条不同的路径?
样例
1,1 1,2 1,3 1,4 1,5 1,6 1,7
2,1            
3,1           3,7

以上3 x 7的网格中,有多少条不同的路径?

注意

n和m均不超过100

解题:

直接数学分析,需要向下走m-1步,在向右走n-1步,共m+n-2步,在这m+n-2步中有m-1步是向下走的,同时向下走的方式确定了,向右走的步也确定了,共有Cm+n-2m-1 种

我们求的是到右下角的路径有多少个,设A[m-1][n-1]就是到该点的路径和,则其路径和等于到临近右侧m-1,n-2的路径和A[m-1][n-2] + 临近上侧m-2,n-1的路径和A[m-2][n-1],

写成通项的形式:A[i][j] = A[i][j-1] + A[i-1][j]

对于初始化:A[i][0] = 1 A[0][j] = 1 ,这里利用到的是杨辉三角的思想

Java程序:

public class Solution {
    /**
     * @param n, m: positive integer (1 <= n ,m <= 100)
     * @return an integer
     */
    public int uniquePaths(int m, int n) {
        // write your code here 
        int arr[][] = new int[m][n];
        for(int i=0;i<m;i++)
            arr[i][0] = 1;
        for(int i=0;i<n;i++)
            arr[0][i] = 1;
        for(int i=1;i<m;i++){
            for(int j=1;j<n;j++)
                arr[i][j] = arr[i][j-1] + arr[i-1][j];
        }
        return arr[m-1][n-1];
    }
}
View Code

Python代码:

class Solution:
    """
    @param n and m: positive integer(1 <= n , m <= 100)
    @return an integer
    """ 
    def uniquePaths(self, m, n):
        # write your code here
        A = [[0 for _ in range(n)] for _ in range(m)]
        for i in range(m):
            A[i][0] = 1
        for j in range(n):
            A[0][j] = 1
        for i in range(1,m):
            for j in range(1,n):
                A[i][j] = A[i][j-1] + A[i-1][j]
        return A[m-1][n-1]
View Code

官方给的方法:利用深度优先的方法,时间复杂度O(n4)空间复杂度(n)

Java程序:

public class Solution {
    /**
     * @param n, m: positive integer (1 <= n ,m <= 100)
     * @return an integer
     */
    public int uniquePaths(int m, int n) {
        // write your code here 
        if(m<0||n<0) return 0;
        if(m==1 && n==1) return 1;
        return uniquePaths(m-1,n) + uniquePaths(m,n-1);
    }
}
View Code

运行到27%的测试程序,运行超时

官方解题报告中又讲到利用深度搜索+缓存的方法 叫备忘录法

这里说的时间复杂度是O(n2)空间复杂O(n2) 不是很理解,同时程序只是对非零项进行计算,竟然可以通过测试

Java程序:

public class Solution {
    /**
     * @param n, m: positive integer (1 <= n ,m <= 100)
     * @return an integer
     */
     
    public int uniquePaths(int m, int n) {
        // write your code here 
        //00 未用到
        int[][] f= new int[m+1][n+1];
        return dfs(f,m,n);
    }
    private int dfs(int[][] f,int m,int n){
        if(m<1 || n<1) return 0;
        if(m==1 && n==1) return 1;
        return getOrUpdate(f,m-1,n) + getOrUpdate(f,m,n-1);
    }
    private int getOrUpdate(int[][] f,int m,int n){
        if(f[m][n]>0) return f[m][n];
        else {
            f[m][n] = dfs(f,m,n);
            return f[m][n];
        }
    }
}
View Code

Python程序:

class Solution:
    """
    @param n and m: positive integer(1 <= n , m <= 100)
    @return an integer
    """ 
    def uniquePaths(self, m, n):
        # write your code here
        f = [[0 for _ in range(n+1)] for _ in range(m+1)]
        return self.dfs(f,m,n)
    def dfs(self,f,m,n):
        if m<1 or n<1 : return 0
        if m==1 and n==1 : return 1
        return self.getOrUpdate(f,m-1,n) + self.getOrUpdate(f,m,n-1)
    def getOrUpdate(self,f,m,n):
        if f[m][n]>0 :
            return f[m][n]
        else:
            f[m][n] = self.dfs(f,m,n)
            return f[m][n]
View Code

在上面的深度优先算法中,有重复计算

而通过getOrUpdate方法,只对f[m][n]==0的情况进行在找路径

不同的路径 II

Unique Paths 2

题目:

跟进“不同的路径”:

现在考虑网格中有障碍物,那样将会有多少条不同的路径?

网格中的障碍和空位置分别用10来表示。

 
样例

如下所示在3x3的网格中有一个障碍物:

[

  [0,0,0],

  [0,1,0],

  [0,0,0]

]

一共有2条不同的路径从左上角到右下角。

注意

m和n均不超过100

解题:

Java程序:

public class Solution {
    /**
     * @param obstacleGrid: A list of lists of integers
     * @return: An integer
     */
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        // write your code here
        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;
        if(obstacleGrid[0][0]==1 || obstacleGrid[m-1][n-1]==1) return 0;
        int A[][] = new int[m][n];
        A[0][0] = obstacleGrid[0][0]==1?0:1;
        for(int i=1;i<m;i++)
            A[i][0] = obstacleGrid[i][0]==1?0:A[i-1][0];
        for(int j=1;j<n;j++)
            A[0][j] =obstacleGrid[0][j]==1?0:A[0][j-1];
        for(int i=1;i<m;i++)
            for(int j=1;j<n;j++)
                A[i][j] = obstacleGrid[i][j]==1?0:A[i][j-1]+ A[i-1][j];
                         
        return A[m-1][n-1];
            
    }
}
View Code

Python程序:

class Solution:
    """
    @param obstacleGrid: An list of lists of integers
    @return: An integer
    """
    def uniquePathsWithObstacles(self, obstacleGrid):
        # write your code here
        
        m ,n= len(obstacleGrid),len(obstacleGrid[0])
        if obstacleGrid[0][0]==1 or obstacleGrid[m-1][n-1]==1 : return 0
        A = [[0 for _ in range(n)] for _ in range(m)]
        A[0][0] = 0 if obstacleGrid[0][0]==1 else 1
        for i in range(1,m):
            A[i][0] = 0 if obstacleGrid[i][0]==1 else A[i-1][0]
        for j in range(1,n):
            A[0][j] = 0 if obstacleGrid[0][j]==1 else A[0][j-1]
        for i in range(1,m):
            for j in range(1,n):
                A[i][j] = 0 if obstacleGrid[i][j]==1 else A[i-1][j]+A[i][j-1]
        return A[m-1][n-1]
View Code

这个是在上面程序的基础上进行修改,对于边界点,先找到通路,自己所在的位置可达,就依赖于上一点是否是通路

对于中间点也是,自己所在的位置可达,就依赖于其临近左侧和上侧点的情况了

两个字符串是变位词

Two Strings Are Anagrams

题目:

写出一个函数 anagram(s, t) 去判断两个字符串是否是颠倒字母顺序构成的

样例

给出 s="abcd",t="dcab",返回 true

Challenge

O(n) time, O(1) extra space

解题:

定义一个HashMap,key=字符串中的每个字符,value=字符出现的次数,第一个字符串s每个入HashMap,并更改value的值,第二个字符串t,当key不存在时候或者value《0时候,返回false。

Java程序:

public class Solution {
    /**
     * @param s: The first string
     * @param b: The second string
     * @return true or false
     */
    public boolean anagram(String s, String t) {
        // write your code here
        if(s.length()!=t.length())
            return false;
        int len = s.length();
        HashMap map = new HashMap();
        for(int i=0;i<len;i++){
            char ch = s.charAt(i);
            if(map.containsKey(ch)==false){
                map.put(ch,1);// key value
            }else{
                int tmpvalue = (Integer) map.get(ch) + 1;
                map.put(ch,tmpvalue);
            }
        }
           
        for(int i=0;i<len;i++){
            char ch = t.charAt(i);
            if(map.containsKey(ch)==false){
                return false;
            }else{
                int tmpvalue = (Integer) map.get(ch) - 1;
                map.put(ch,tmpvalue);
                if((Integer) map.get(ch)<0) 
                    return false;
            }
        }
        
            return true;
    }
};
View Code

这里时间复杂度是O(n),空间复杂度也是O(n)

网上看到下面的方法,256个字符,定义一个长度是256的数组,存放每个字符出现的次数

Java程序:

public class Solution {
    /**
     * @param s: The first string
     * @param b: The second string
     * @return true or false
     */
    public boolean anagram(String s, String t) {
        // write your code here
        if(s.length()!=t.length())
            return false;
        int len = s.length();
        int A[] = new int[256];
        // int tA[] = new int[256];
        for(int i=0;i<len;i++)
            A[s.charAt(i)]++;
        
        for(int i=0;i<len;i++)
            A[t.charAt(i)]--;
        
        for(int i=0;i<256;i++)
            if(A[i]!=0)
                return false;
        return true;
    }
}
View Code

Python程序:

class Solution:
    """
    @param s: The first string
    @param b: The second string
    @return true or false
    """
    def anagram(self, s, t):
        # write your code here
        if len(s) != len(t):
            return False
        dict={}
        
        for si in s:
            if dict.has_key(si)==False:
                dict[si] = 1
            else:
                dict[si] = dict.get(si) + 1
        for ti in t:
            if dict.has_key(ti)==False:
                return False
            else:
                dict[ti] = dict.get(ti) - 1
                if dict[ti] < 0:
                    return False
        return True
View Code

利用到python的字典和HashMap差不多的

两个链表的和

Add Two Numbers

题目:

你有两个用链表代表的整数,其中每个节点包含一个数字。数字存储按照在原来整数中相反的顺序,使得第一个数字位于链表的开头。写出一个函数将两个整数相加,用链表形式返回和。

样例

给出两个链表 3->1->5->null 和 5->9->2->null,返回 8->0->8->null

解题:

 链表求和,判断是否进位,链表是否结束,和之前leetcode上的题目一样,由于节点搞错了,搞了好久的

Java程序:

/**
 * 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) {
        // write your code here
        
        ListNode head= new ListNode(0);
        ListNode current = head;
        int quotients=0;
        while(l1!=null && l2!=null){
            int sum = quotients + l1.val + l2.val;
            quotients = sum/10;
            // l1.val = sum%10;
            current.next = new ListNode(sum%10);
            current = current.next;
            l1 = l1.next;
            l2 = l2.next;
        }
        while(l1!=null){
            int sum = quotients + l1.val;
            quotients = sum/10;
            current.next = new ListNode(sum%10);
            current = current.next;
            l1 = l1.next;
        }
        
        while(l2!=null){
            int sum = quotients + l2.val;
            quotients = sum/10;
            current.next = new ListNode(sum%10);
            current = current.next;
            l2 = l2.next;
        }
        if(quotients==1){
            current.next = new ListNode(1);
            current = current.next;
         
        }
        return head.next;
    }
}
View Code

Python程序:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    # @param l1: the first list
    # @param l2: the second list
    # @return: the sum list of l1 and l2 
    def addLists(self, l1, l2):
        # write your code here
        head = ListNode(0)
        current = head;
        sum = 0
        while l1!=None or l2!=None:
            if l1!=None:
                sum+=l1.val
                l1=l1.next
            if l2!=None:
                sum+=l2.val
                l2=l2.next
            current.next = ListNode(sum%10)
            current = current.next
            sum/=10
        if sum==1:
            current.next = ListNode(1)
            current = current.next
        return head.next
View Code

中位数

Median

题目:

给定一个未排序的整数数组,找到其中位数。

中位数是排序后数组的中间值,如果数组的个数是偶数个,则返回排序后数组的第N/2个数。

 
样例

给出数组[4, 5, 1, 2, 3], 返回 3

给出数组[7, 9, 4, 5],返回 5

挑战

时间复杂度为O(n)

 解题:

利用冒泡排序,一次排序介绍后能够回到最后的位置,若是升序排序,每次都要数回到较大的位置,第一次,最大元素到位,第二次,次大元素到位,...,

第len/2-1(奇数长度时候是len/2)次回到自己的位置,也就是中位数的位置,但是这里的时间复杂度是O(n2)

由于存在只有一个元素的情况,不满足冒泡排序,直接返回第0个元素。

Java程序:

public class Solution {
    /**
     * @param nums: A list of integers.
     * @return: An integer denotes the middle number of the array.
     */
    public int median(int[] nums) {
        // write your code here
        int left = 0;
        int len = nums.length;
        if(len%2==1)
            return BubbleSort(nums,len/2,len);
        else
            return BubbleSort(nums,len/2-1,len);
        
    }
    int BubbleSort(int[] nums,int mid,int len){
        int i,j,flag;
        int tmp;
        for(i=len-1;i>=1;i--){
            flag = 0;
            for(j=1;j<=i;++j)
                if(nums[j-1]>nums[j]){
                    tmp = nums[j];
                    nums[j] = nums[j-1];
                    nums[j-1] = tmp;
                    flag = 1;
                    
                }
            if(i==mid)
                return nums[i];
        }
        return nums[0];
    }
}
View Code

总耗时: 3139 ms

下面是利用到快速排序的思想,每次找到第k大的数,同时又划分数据集,一个比他大,一个比他小的,再选取合适的范围进行调整,这里开始自己写,测试程序运行到32%处报错,一直修改不好,下面是参考网上程序修改如下:

public class Solution {
    /**
     * @param nums: A list of integers.
     * @return: An integer denotes the middle number of the array.
     */
    public int median(int[] nums) {
        // write your code here
        int left = 0;
        int len = nums.length;
        if(len%2==1)
            return findKth(nums,len/2,0,len-1);
        else
            return findKth(nums,len/2-1,0,len-1);
        
    }

    public int findKth(int[]nums, int mid,int left,int right){
        if(mid==left && left ==right) 
            return nums[mid];
        if(left>=right) 
            return -1;
        
        int pivot;
        int i=left,j=right;

        pivot = nums[left];
        while(i!=j){
            while(j>i && nums[j]>=pivot) --j;
                nums[i] = nums[j];
            while(i<j&&nums[i]<=pivot) ++i;
                nums[j] = nums[i];
        }
        nums[i] = pivot;
            
        if(i==mid) 
            return nums[i];
        else if(i>mid) 
            return partitions(nums, mid, left, i-1);
        else 
            return partitions(nums, mid, i+1, right);
    }
}
View Code

总耗时: 2358 ms

我记忆中的快速排序是这样的,开始我搞错的原因就是结束条件搞错了

public class Solution {
    /**
     * @param nums: A list of integers.
     * @return: An integer denotes the middle number of the array.
     */
    public int median(int[] nums) {
        // write your code here
        int left = 0;
        int len = nums.length;
        if(len%2==1)
            return fintKth(nums,len/2,0,len-1);
        else
            return fintKth(nums,len/2-1,0,len-1);
        
    }

    public int fintKth(int[]nums, int mid,int left,int right){
        if(mid==left && left ==right) 
            return nums[mid];
        if(left>=right) 
            return -1;
        
        
        int i=left;
        int j=right;
 
        int pivot = nums[left];
        while(i!=j){
            while(j>i && nums[j]>pivot) --j;
                if(i<j){
                    nums[i] = nums[j];
                    ++i;
                }
            
            while(i<j&&nums[i]<pivot) ++i;
            if(i<j){
                nums[j] = nums[i];
                --j;
            }
            }
            nums[i] = pivot;
        
        if(i==mid) 
            return nums[i];
        else if(i>mid ) 
            return partitions(nums, mid, left, i-1);
        else 
            return partitions(nums, mid, i+1, right);
  
    }
}
View Code

总耗时: 2997 ms

Python程序:

class Solution:
    """
    @param nums: A list of integers.
    @return: An integer denotes the middle number of the array.
    """
    def median(self, nums):
        # write your code here
        left = 0
        right = len(nums)
        mid = right/2
        if right%2==1:
            return self.findKth(nums,mid,left,right-1)
        elif right%2==0:
            return self.findKth(nums,mid-1,left,right-1)
    
    def findKth(self,nums,mid,left,right):
        if left==mid and mid == right:
            return nums[mid]
        if left>right:
            return -1
        i = left
        j = right
        pivot = nums[left]
        while(i<j):
            while(i<j and nums[j]>=pivot):
                j-=1
            if i<j:
                nums[i] = nums[j]
            while(i<j and nums[i]<=pivot):
                i+=1
            if i<j:
                nums[j] = nums[i]
        nums[i] = pivot
        if i == mid:
            return nums[mid]
        elif i>mid:
            return self.findKth(nums,mid,left,(i-1))
        elif i<mid:
            return self.findKth(nums,mid,(i+1),right)
View Code

总耗时: 475 ms

主元素

Majority Number

题目:

给定一个整型数组,找出主元素,它在数组中的出现次数严格大于数组元素个数的二分之一。

样例

给出数组[1,1,1,1,2,2,2],返回 1

挑战

要求时间复杂度为O(n),空间复杂度为O(1)

解题:

利用HashMap,key=这个数,value=这个数出现的次数,当发现出现次数大于len/2的时候结束,返回这个数就是majority number,但是这里的时间复杂度和空间复杂度都是O(n)

Java程序:

public class Solution {
    /**
     * @param nums: a list of integers
     * @return: find a  majority number
     */
    public int majorityNumber(ArrayList<Integer> nums) {
        // write your code
        int numsLen = nums.size();
        HashMap hmap = new HashMap();
        int majority = 0;
        for(int i = 0;i<numsLen;i++){
            int num = nums.get(i);
            if(hmap.containsKey(num)==false){
                hmap.put(num,1);
            }else{
                hmap.put(num,(Integer)hmap.get(num)+1);
                if((Integer)hmap.get(num)>numsLen/2){
                    majority= num;
                    break;
                }
            }
        }
        return majority;
    }
}
View Code

总耗时: 2294 ms

 上面程序有点缺陷,只在第二次出现的时候才返回majority number,定义的初始majority = 0,测试数据中有一个只有一个0长度也是1,造成无法测出错误

修改后:

public class Solution {
    /**
     * @param nums: a list of integers
     * @return: find a  majority number
     */
    public int majorityNumber(ArrayList<Integer> nums) {
        // write your code
        int numsLen = nums.size();
        HashMap hmap = new HashMap();
        int majority = 0;
        for(int i = 0;i<numsLen;i++){
            int num = nums.get(i);
            if(hmap.containsKey(num)==false)
                hmap.put(num,1);
            else
                hmap.put(num,(Integer)hmap.get(num)+1);
            if((Integer)hmap.get(num)>numsLen/2){
                majority= num;
                break;
                }
            }
        
        return majority;
    }
}
View Code

总耗时: 2152 ms

 Python程序:

class Solution:
    """
    @param nums: A list of integers
    @return: The majority number
    """
    def majorityNumber(self, nums):
        # write your code here
        numsLen = len(nums)
        d={}
        for num in nums:
            if num not in d:
                d[num] = 1
            else:
                d[num] +=1
            if d[num]>numsLen/2:
                return num
View Code

总耗时: 549 ms

网上看到,利用快速排序的思想,中位数一定是主元素,这里和上一题有很对应了。直接利用上面的找中位数的程序

Java程序:

public class Solution {
    /**
     * @param nums: a list of integers
     * @return: find a  majority number
     */
    public int majorityNumber(ArrayList<Integer> nums) {
        // write your code
        int numsLen = nums.size();
        int mid = numsLen/2;
        int left = 0;
        int right = numsLen - 1;
        return findKth(nums,mid,left,right);
    }
    int findKth(ArrayList<Integer> nums,int mid,int left,int right){
        if(mid==left && mid == right)
            return nums.get(mid);
        if(left>=right)
            return -1;
        int i=left;
        int j=right;
        int pivot=nums.get(left);
        while(i<j){
            while(i<j && nums.get(j)>pivot) j--;
            if(i<j){
                nums.set(i,nums.get(j));
                i++;
            }
            while(i<j && nums.get(i)<pivot) i++;
            if(i<j){
                nums.set(j,nums.get(i));
                j--;
            }
            
        }
        nums.set(i,pivot);
        if(i==mid) 
            return nums.get(mid);
        else if(i>mid)
            return findKth(nums,mid,left,i-1);
        else 
            return findKth(nums,mid,i+1,right);
    }
}
View Code

总耗时: 2193 ms

这里的时间复杂度我一直感觉是快速排序的时间复杂度O(nlogn),为什么都说是O(n)?不明白。。。空间复杂度道是O(1)

网上看到这样一种思想,同时删除不相同的两个元素,最后剩余的元素一定是主元素,题目已经限制了主元素个数大于len/2,删除后一定余的是主元素。这里给的ArrayList类型数组,好像在提醒用这个方法。

ArrayList不熟悉,多少尝试都失败,在网上看到,通过记录一个元素出现的次数,是这个元素时候计数器+1,不是的时候-1,当时0的时候重新计数,这是01的原则,也实现了同时删除两个数,最后的计数器对于的元素就是答案。

Java程序:

public class Solution {
    /**
     * @param nums: a list of integers
     * @return: find a  majority number
     */
    public int majorityNumber(ArrayList<Integer> nums) {
        // write your code
        int numsLen = nums.size();
        if(numsLen==1) 
            return nums.get(0);
       int times=0;
       int maj = 0;
       for(int i=0;i<numsLen;i++){
           if(times==0){
               maj = nums.get(i);
               times= 1;
           }else{
               if(maj==nums.get(i))
                    times++;
                else
                    times--;
           }
       }
       return maj;
    }
}
View Code

总耗时: 2373 ms

这里也要求这个元素出现次数大于len/2,否则,可在在刚开始就剔除了这个元素,如[1,1,1,2,2,3,3,4,4,5],这个结果就是4了。

Python程序:

class Solution:
    """
    @param nums: A list of integers
    @return: The majority number
    """
    def majorityNumber(self, nums):
        # write your code here
        numsLen = len(nums)
        if numsLen == 1 :
            return nums[0]
        times = 0
        maj = 0
        for num in nums:
            if times==0:
                times=1
                maj = num
            elif maj==num:
                times +=1
            else:
                times -=1
        return maj
View Code

总耗时: 350 ms

这里看到,可以求第二多的元素

Java程序:

public class Solution {
    /**
     * @param nums: a list of integers
     * @return: find a  majority number
     */
    public int majorityNumber(ArrayList<Integer> nums) {
        // write your code
        int first = Integer.MIN_VALUE; // the number with the top votes
        int firstVote = 0; // the top votes
        int second = Integer.MIN_VALUE; // the number with the second top votes
        int secondVote = 0; // the second top votes
        int numsLen = nums.size();
        if(numsLen==1)
            return nums.get(0);
        for(int i=0;i<numsLen;i++){
            if(firstVote > 0 && nums.get(i) == first) {
                    firstVote++;
            } else if(secondVote > 0 && nums.get(i) == second) {
                    secondVote++;
                if(secondVote > firstVote) {
                    int t = first;
                    first = second;
                    second = t;
                    t = firstVote;
                    firstVote = secondVote;
                    secondVote = t;
                }
            } else if(firstVote == 0) {
                    first = nums.get(i);
                    firstVote++;
                    } else if(secondVote == 0) {
                                second = nums.get(i);
                                secondVote++;
                        }  else {
                                firstVote--;
                                secondVote--;
                        }
        }
                // confirm if the number with top 2 votes occurs more than 3/n times
                // int firstCount = 0;
                // int secondCount = 0;
                // for(int i=0;i<numsLen;i++) {
                        // if(firstVote > 0 && nums.get(i) == first) firstCount++;
                        // if(secondVote > 0 && nums.get(i) == second) secondCount++;
                // }
                // if(firstCount > numsLen / 3) return first;
                // else if(secondCount > numsLen / 3) return second; 
                // else return 0;
                return first;
    }
}
View Code

总耗时: 1864 ms

寻找缺失的数

题目:

给出一个包含 0 .. N 中 N 个数的序列,找出0 .. N 中没有出现在序列中的那个数。

 
样例

N = 4 且序列为 [0, 1, 3] 时,缺失的数为2

注意

可以改变序列中数的位置。

挑战

在数组上原地完成,使用O(1)的额外空间和O(N)的时间。

Java程序:

官方给的C++,改写成java运行超时

public class Solution {
    /**    
     * @param nums: an array of integers
     * @return: an integer
     */
    public int findMissing(int[] nums) {
        // write your code here
        nums = bucket_sort(nums);
        int n = nums.length;
        for(int i=0;i<n;++i){
            if(nums[i] != (i+1))
                return i+1;
        }
        return n+1;
    }
    public int[] bucket_sort(int [] nums){
        int n = nums.length;
        for(int i=0;i<n;++i){
            while(nums[i] !=i+1){
                if(nums[i]<=0 ||nums[i]>n || nums[i] ==nums[nums[i]-1])
                    break;
                int tmp = nums[i];
                nums[i] = nums[nums[i] - 1];
                nums[nums[i] - 1] =tmp;
            }
        }
        return nums;
    }
}
View Code

异或更简单,因为 i^i = 0

public class Solution {
    /**    
     * @param nums: an array of integers
     * @return: an integer
     */
    public int findMissing(int[] nums) {
        // write your code here
        if(nums == null || nums.length == 0)
            return 0;
        int result = 0;
        for(int i = 0;i<nums.length;i++){
            result^=i;
            result^=nums[i];
        }
        result^=nums.length;
        return result;
    }
}
原文地址:https://www.cnblogs.com/bbbblog/p/4859707.html