java&python版剑指offer(五)

本文按照牛客网的顺序,牛客网剑指offer刷题网址:https://www.nowcoder.com/ta/coding-interviews

本篇涉及的题目有:
1、数组中出现次数超过一半的数字
2、最小的K个数
3、连续子数组的最大和
4、把数组排成最小的数
5、丑数
6、数组中的逆序对

1、数组中出现次数超过一半的数字

问题描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

思路解析
假设有数字超过数组长度的一半,我们使用一个计数器,如果该数字出现一次,计数器加一,如果不是该数字,计数器减一,那么到最后,计数器一定是大于0的。那么我们可以按照如下的规则:我们首先假设最终的结果是数组的第一个数,计数器初始为1。从第二个数开始遍历,如果与当前的数相同,计数器加1,如果不同,判断计数器的状态,如果大于0,则减一;如果等于零,则置1。同时将假设的最终结果变为当前的数。
这里最后要判断最后的结果是不是真的出现了一半以上的次数。

代码实现
java

public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        if(array.length==0)
            return 0;
        int res = array[0];
        int count = 1;
        for(int i=1;iarray.length / 2)
            return res;
        else
            return 0;
    }
}

python

# -*- coding:utf-8 -*-
class Solution:
    def MoreThanHalfNum_Solution(self, numbers):
        # write code here
        res = numbers[0]
        count = 1
        for num in numbers[1:]:
            if num == res:
                count = count + 1
            else:
                if count == 0:
                    res = num
                    count = 1
                else:
                    count = count - 1
        count = 0
        for num in numbers:
            if num == res:
                count = count + 1
        if count > len(numbers) / 2:  
            return res
        else:
            return 0

2、最小的K个数

问题描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

思路解析
使用堆排序,找到最小的K个数。

代码实现
java

import java.util.*;
public class Solution {
    public ArrayList GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList arr=new ArrayList();
        int len=input.length;
        if(k>len)
            return arr;
        for(int i=0;i=i;j--){
              int p=(j+i-1)/2;
            if(input[p]>input[j]){
                int temp=input[p];
                input[p]=input[j];
                input[j]=temp;
            }   
        }      
    }
}

python

# -*- coding:utf-8 -*-
class Solution:
    
    def GetLeastNumbers_Solution(self, tinput, k):
        # write code here
        if len(tinput) < k or k==0:
            return []
        self.buildHeap(tinput[:k],k)
        for i in range(k,len(tinput)):
            if tinput[i] > self.heap[0]:
                continue
            else:
                self.heap[0] = tinput[i]
                self.perceDown(0,k)
        return sorted(self.heap)
        
    def buildHeap(self,tinput,k):
        self.heap = tinput
        for i in range(k//2,-1,-1):
            self.perceDown(i,k)
            
    def perceDown(self,i,k):
        temp = self.heap[i]
        while (2 * i + 1) < k:
            child = 2 * i + 1
            if (child < k - 1) and self.heap[child] < self.heap[child+1]:
                child = child + 1
            if temp < self.heap[child]:
                self.heap[i] = self.heap[child]
                i = child
            else:
                break
        self.heap[i] = temp       

3、连续子数组的最大和

问题描述
HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。你会不会被他忽悠住?(子向量的长度至少是1)

思路解析
这道题跟之前我在网易面试的股票买卖问题类似,采用的叫Kadane's Algorithm的方法,用两个指针。maxSum指针记录此前所有碰到的最大值,curSum指针记录循环到当前元素这一轮的最大值。当循环到元素i时,如果i+curSum < i的话,说明此前的和是负的,需要舍弃,所以将curSum的值变为i,反之,将curSum的值变为i+curSum,表明当前的和还是正值,可以继续向前探索,由于每一次遍历一个元素之后都会比较一下curSum和maxSum,所以可以放心的继续向前遍历。

代码实现
java

public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {
        if(array.length==0)
            return 0;
        int maxCur = array[0];
        int maxSoFar = array[0];
        for(int i = 1;i

python

# -*- coding:utf-8 -*-
class Solution:
    def FindGreatestSumOfSubArray(self, array):
        # write code here
        maxCur = array[0]
        maxSoFar = array[0]
        for t in array[1:]:
            maxCur = max(t,maxCur + t)
            maxSoFar = max(maxSoFar,maxCur)
        return maxSoFar

4、把数组排成最小的数

问题描述
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

思路解析
这道题其实希望我们能够找到一个排序规则,数组根据这个规则排序之后能排成一个最小的数字。要确定排序的规则,就要比较两个数字,也就是给出两个数字m和n,我们需要确定一个规则判断m和n哪个应该排在前面,而不是仅仅比较这两个数字的值哪个更大。

根据题目的要求,两个数字m和n能拼接称数字mn和nm。如果mn

代码实现
java

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Solution {
    public String PrintMinNumber(int [] numbers) {
        int n;
        String s="";
        ArrayList list=new ArrayList();
        n=numbers.length;
         
        for(int i=0;i(){
         
            @Override
            public int compare(Integer str1, Integer str2) {
                // TODO Auto-generated method stub         
                    String s1=str1+""+str2;
                    String s2=str2+""+str1;
                     
                    return s1.compareTo(s2);
                }
            });
         
        for(int j:list){
            s+=j;
        }
        return s;
    }
}

python

# -*- coding:utf-8 -*-
class Solution:
    def PrintMinNumber(self, numbers):
        # write code here]
        if not len(numbers):
            return ""
        arr = [str(x) for x in numbers]
        arr.sort(lambda x,y:cmp(x+y,y+x))
        return int("".join(arr))

5、丑数

问题描述
把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

思路解析
暴力求解丑数是不可行的,使用动态规划的解法,首先我们要确保数组里的已有的丑数是排好序的,同时要维护三个索引。

代码实现
java

import java.util.*;
public class Solution {
    public int GetUglyNumber_Solution(int index) {
        if(index == 0)
            return 0;
        int index2 = 0;
        int index3 = 0;
        int index5 = 0;
        ArrayList arr = new ArrayList();
        arr.add(1);
        int nextMin=1;
        for(int i=2;i<=index;i++){
            nextMin = Math.min(Math.min(arr.get(index2) * 2,arr.get(index3) * 3),arr.get(index5) * 5);
            arr.add(nextMin);
            if(arr.get(index2) * 2 <= nextMin)
                index2 += 1;
            if(arr.get(index3) * 3 <= nextMin)
                index3 += 1;
            if(arr.get(index5) * 5 <= nextMin)
                index5 += 1;
        }
        return nextMin;
    }
}

python

# -*- coding:utf-8 -*-
class Solution:
    def GetUglyNumber_Solution(self, index):
        # write code here
        if index<=0:
            return 0
        res = [1]
        index2 = 0
        index3 = 0
        index5 = 0
        while(len(res) < index):
            
            nextMin = min(res[index2] * 2,res[index3] * 3,res[index5] * 5)
            res.append(nextMin)
            while res[index2] * 2 <= nextMin:
                index2 = index2 + 1
            while res[index3] * 3 <= nextMin:
                index3 = index3 + 1
            while res[index5] * 5 <= nextMin:
                index5 = index5 + 1
        return res[-1]

6、数组中的逆序对

问题描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007

思路解析
使用归并排序的思路进行求解

代码实现
java

import java.io.*;
import java.util.*;
public class Main {
    public static int InversePairs(int [] array) {
        if(array==null||array.length==0)
        {
            return 0;
        }
        int[] copy = new int[array.length];
        for(int i=0;i>1;
        int leftCount = InversePairsCore(array,copy,low,mid)%1000000007;
        int rightCount = InversePairsCore(array,copy,mid+1,high)%1000000007;
        int count = 0;
        int i=mid;
        int j=high;
        int locCopy = high;
        while(i>=low&&j>mid)
        {
            if(array[i]>array[j])
            {
                count += j-mid;
                copy[locCopy--] = array[i--];
                if(count>=1000000007)//数值过大求余
                {
                    count%=1000000007;
                }
            }
            else
            {
                copy[locCopy--] = array[j--];
            }
        }
        for(;i>=low;i--)
        {
            copy[locCopy--]=array[i];
        }
        for(;j>mid;j--)
        {
            copy[locCopy--]=array[j];
        }
        for(int s=low;s<=high;s++)
        {
            array[s] = copy[s];
        }
        return (leftCount+rightCount+count)%1000000007;
    }

python

# -*- coding:utf-8 -*-
class Solution:
    def InversePairs(self, data):
        # write code here
        if len(data) > 1:
            mid = len(data) / 2
            left_half = data[:mid]
            right_half = data[mid:]
            left_count = self.InversePairs(left_half)%1000000007
            right_count = self.InversePairs(right_half)%1000000007
            i,j,k,count = len(left_half)-1,len(right_half)-1,len(data)-1,0
            while i >= 0 and j >= 0:
                if left_half[i] < right_half[j]:
                    data[k] = right_half[j]
                    j = j - 1
                    k = k - 1
                else:
                    data[k] = left_half[i]
                    count += (j+1)
                    i = i - 1
                    k = k - 1
            while i >= 0:
                data[k] = left_half[i]
                k = k - 1
                i = i - 1
            while j>=0:
                data[k] = right_half[j]
                k = k - 1
                j = j - 1
            return (count + left_count + right_count)%1000000007
        else:
            return 0

你可能感兴趣的:(java&python版剑指offer(五))