剑指offer 数组专题 刷题记录

剑指Offer(一):二维数组中的查找

//二分查找

public class Solution {
    public boolean Find(int target, int [][] array) {
        if(array.length==0||array==null){
            return false;
        }
        for(int i=0;i<array.length;i++){
            int begin=0;
            int end=array[i].length-1;
            while(begin<=end){
               int mid=(begin+end)/2;
                if(target==array[i][mid]){
                    return true;
                }else if(target<array[i][mid]){
                    end=mid-1;
                }else if(target>array[i][mid]){
                    begin=mid+1;
                }
            }
            
        }
        return false;
    }
}

//观察规律

public class Solution {
    public boolean Find(int target, int [][] array) {

        int row=0;
        int col=array[0].length-1;
        
        while(row<array.length&&col>=0){
            if(array[row][col]==target){
                return true;
            }else if(target>array[row][col]){
                row++;
            }else if(target<array[row][col]){
                col--;
            }
        }
        return false;
    }
}

剑指Offer(六):旋转数组的最小数字

//参考剑指offer ,将数组分为两个子数组

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        //二分查找
        if(array.length==0||array==null){
            return 0;
        }
        int start=0;
        int end=array.length-1;
        int mid=0;
        
        while(array[start]>=array[end]){
            if(end-start==1){
                return array[end];
            }
            mid=start+(end-start)/2;
            if(array[mid]>=array[start]){
                start=mid;
            }else{
                end=mid;
            }
        }
        return array[mid];
    }
}

面试题11:旋转数组的最小值

剑指Offer(十三):调整数组顺序使奇数位于偶数前面

//两个数组,时间换空间

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param array int整型一维数组 
     * @return int整型一维数组
     */
    public int[] reOrderArray (int[] array) {
        ArrayList<Integer> oddList = new ArrayList<>();
        ArrayList<Integer> evenList = new ArrayList<>();
        int[] res = new int[array.length];
        for (int i = 0; i < array.length; i++) {
            if (0 == array[i] % 2) {
                // 偶数
                evenList.add(array[i]);
            } else {
                // 奇数
                oddList.add(array[i]);
            }
        }
        for (int i = 0; i < oddList.size(); i++) {
            res[i] = oddList.get(i);
        }
        int index = oddList.size();
        for (int i = 0; i < evenList.size(); i++) {
            res[index] = evenList.get(i);
            index++;
        }
        return res;
    }
}
//解题思路
/*(O(n),O(n))
遍历两次数组,第一次只添加奇数到新数组里,第二次只添加奇数到新数组里
 */

public int[] reOrderArray (int[] array) {
    int index = 0;
    int[] res = new int[array.length];
    for (int i : array) {
        if (i % 2 != 0) {
            res[index] = i;
            index++;
        }
    }
    for (int i : array) {
        if (i % 2 == 0) {
            res[index] = i;
            index++;
        }
    }
    return res;
}

核心的解法:头尾指针,类似快排的方法

class Solution {
    public int[] exchange(int[] nums) {
        int left = 0;
        int right = nums.length - 1;
        while (left < right) {
            while (left < right && nums[left] % 2 != 0) {
                left++;
            }
            while (left < right && nums[right] % 2 == 0) {
                right--;
            }
            if (left < right) {
                int temp = nums[left];
                nums[left] = nums[right];
                nums[right] = temp;
            }
        }
        return nums;
    }
}

剑指Offer(二十八):数组中出现次数超过一半的数字

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        HashMap<Integer,Integer> list=new HashMap<Integer,Integer>();

        
        for(int i=0;i<array.length;i++){
            
            if(!list.containsKey(array[i])){
                list.put(array[i],1);
                if(2>array.length){
                    return array[i];
                }
            }else{
                int count=list.get(array[i]);
                count++;
                if(count*2>array.length){
                    return array[i];
                }
                list.put(array[i],count);
            }
        }
        
        
 
        
        return 0;
    }
}
import java.util.Arrays;

public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
    	Arrays.sort(array);
        int count=0;
        
        for(int i=0;i<array.length;i++){
            if(array[i]==array[array.length/2]){
                count++;
            }
        }
        if(count>array.length/2){
            return array[array.length/2];
        }else{
            return 0;
        }
        
    }
}

冒泡排序:

 public int[] reOrderArray (int[] array) {
        // write code here
        int[] result = new int[array.length];
        for (int i = 0; i < array.length; i ++) {
            for  (int j = 0; j < array.length-i-1; j ++) {
                if (array[j]%2 == 0 && array[j+1]%2 == 1) {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
        }
        return array;
    }

剑指Offer(三十):连续子数组的最大和

暴力破解方法

import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {
        
        ArrayList<Integer> list=new ArrayList<Integer>();  
        
        for(int i=0;i<array.length;i++){      /这个方法使用暴力破解
            int sum=0;                        /ArrayList的使用
            for(int j=i;j<array.length;j++){  / 得到大小用size;
                sum+=array[j];                //得到某个值,用get(X)坐标
                list.add(sum);
            }
        }
        if(list.size()<0){
            return 0;
        }
        Collections.sort(list);
        return list.get(list.size()-1);          
    }
}

///分析数组规律的方法

public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {
        if(array==null||array.length==0){
            return 0;
        }
        
        int maxValue=0x80000000;
        int countValue=0;
        for(int i=0;i<array.length;i++){
            if(countValue<=0){
                countValue=array[i];
            }else{
                countValue+=array[i];
            }
            
            if(countValue>maxValue){
                maxValue=countValue;
            }
        }
        return maxValue;
        
    }
}

剑指Offer(三十二):把数组排成最小的数

暴力破解: 比较 两个字符串的大小 s1>s2
在这里插入图片描述

public class Solution {
    public String PrintMinNumber(int [] numbers) {
        String str = "";
		for (int i=0; i<numbers.length; i++){
			for (int j=i+1; j<numbers.length; j++){
				int a = Integer.valueOf(numbers[i]+""+numbers[j]);
				int b = Integer.valueOf(numbers[j]+""+numbers[i]);
				if (a > b){
					int t = numbers[i];
					numbers[i] = numbers[j];
					numbers[j] = t;	
				}
				
			}
		}
		for (int i = 0; i < numbers.length; i++) {
			str += String.valueOf(numbers[i]);
		}
		return str;
    }
}

剑指Offer(三十五):数组中的逆序对

归并排序

public class Solution {
    public int InversePairs(int [] array) {
        if(array.length==0||array==null){
            return 0;
        }
        int[] copyArray=new int[array.length];
        int count=InversePairs(array,copyArray,0,array.length-1);
        return count;
    }
    
    public int InversePairs(int[] array,int[] copyArray,int low,int high){
        if(low==high)
            return 0;
        
        int mid=low+(high-low)/2;
        int i=mid;
        int j=high;
        int localCopy=high;
        int count=0;
        
        int leftCount=InversePairs(array,copyArray,low,mid)%1000000007;
        int rightCount=InversePairs(array,copyArray,mid+1,high)%1000000007;
        
        while(i>=low&&j>mid){
            if(array[i]>array[j]){
                copyArray[localCopy--]=array[i--];
                count+=j-mid;
                if(count>1000000007){
                    count=count%1000000007;
                }
            }else{
                copyArray[localCopy--]=array[j--];
            }
        }
        
        while(i>=low){
            copyArray[localCopy--]=array[i--];
        }
        
        while(j>mid){
            copyArray[localCopy--]=array[j--];
        }
        
        for(int k=low;k<=high;k++){
            array[k]=copyArray[k];
        }
        
        return  (leftCount+rightCount+count)%1000000007;
    }
}

剑指Offer(三十七):数字在排序数组中出现的次数

简单做法

public class Solution {
    public int GetNumberOfK(int [] array , int k) {
        int count=0;
       for(int i=0;i<array.length;i++){
           if(array[i]==k){
               count++;
           }
       }
        return count;
    }
}

二分查找

二分查找,参考剑指Offer,但是用的非递归。

public class Solution {
    	public  int GetNumberOfK(int[] array,int k){
		if(array==null||array.length==0)
			return 0;
		int first=getFirstK(array,k,0,array.length-1);
		int last=getLastK(array,k,0,array.length-1);
		if(first==-1 ||last==-1){
			return 0;
		}
		else{
			return last-first+1;
		}
		
	}
	
	public  int getFirstK(int[] array,int k,int start,int end){
		while(start<=end){
			int mid=(start+end)/2;
			if(k<array[mid])
				end=mid-1;
			else if(k>array[mid])
				start=mid+1;
			else{
				if((mid>0&&array[mid-1]!=k)||mid==0)
					return mid;
				else{
					end=mid-1;
				}
			}
		}
		return -1;
	}
	
	public  int getLastK(int[] array,int k ,int start,int end){
		while(start<=end){
			int mid=(start+end)/2;
			if(k<array[mid])
				end=mid-1;
			else if(k>array[mid])
				start=mid+1;
			else{
				if((mid<array.length-1&&array[mid+1]!=k)||mid==array.length-1)
					return mid;
				else{
					start=mid+1;
				}
			}
		}
		return -1;
	}
}

剑指Offer(四十):数组中只出现一次的数字

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param array int整型一维数组 
     * @return int整型一维数组
     */
    public int[] FindNumsAppearOnce (int[] array) {
        // write code here
        Map<Integer,Integer> map=new HashMap<Integer,Integer>();
        for(int i=0;i<array.length;i++){
            if(map.containsKey(array[i])){
                map.put(array[i],map.get(array[i])+1);
            }else{
                map.put(array[i],1);
            }
        }
        int[] res=new int[2];
        int index=0;
        for(Map.Entry<Integer,Integer> entry:map.entrySet()){
            if(entry.getValue()==1){
                res[index]=entry.getKey();
                index++;
            }
        }
        return res;
    }
}

剑指Offer(五十):数组中重复的数字

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param numbers int整型一维数组 
     * @return int整型
     */
    public int duplicate (int[] numbers) {
        // write code here
        HashMap<Integer,Integer> map=new HashMap<Integer,Integer>();
        for(int i=0;i<numbers.length;i++){
            if(map.containsKey(numbers[i])){
                map.put(numbers[i],map.get(numbers[i])+1);
            }else{
                map.put(numbers[i],1);
            }
        }
        
       for(int i=0;i<numbers.length;i++){
           if(map.get(numbers[i])>1){
               return numbers[i];
           }
       }
        return -1;
    }
}
如果没有重复数字,那么正常排序后,数字i应该在下标为i的位置,所以思路是重头扫描数组,遇到下标为i的数字如果不是i的话,(假设为m),那么我们就拿与下标m的数字交换。在交换过程中,如果有重复的数字发生,那么终止返回ture

class Solution {
    public int findRepeatNumber(int[] nums) {
    
        for(int i=0;i<nums.length;i++){
            while (nums[i]!=i){
                if(nums[i]==nums[nums[i]]){
                    return nums[i];
                }
                int temp=nums[i];
                nums[i]=nums[temp];
                nums[temp]=temp;
            }
        }
        return -1;
    }
}

剑指Offer(五十一):构建乘积数组

通过阶乘构建乘积数组:

import java.util.ArrayList;
public class Solution {
    public int[] multiply(int[] A) {
        if(A==null||A.length==0){
            return A;
        }
        
        int[] B=new int[A.length];
        for(int i=0;i<A.length;i++){
            B[i]=Factrial(A,0,i-1)*Factrial(A,i+1,A.length-1);          
        }
        return B;
    }
    
    public int Factrial(int[] A,int start,int end){
        int temp=1;
        for(int i=start;i<=end;i++){
            temp=temp*A[i];
        }
        return temp;
    }
}

通过观察规律

import java.util.ArrayList;
public class Solution {
    public int[] multiply(int[] A) {
        if(A==null||A.length==0){
            return A;
        }
        
        int[] B=new int[A.length];
        B[0]=1;
        for(int i=1;i<A.length;i++){
            B[i]=B[i-1]*A[i-1];
        }
        
        int temp=1;
        for(int j=A.length-2;j>=0;j--){
            temp*=A[j+1];
            B[j]*=temp;
        }
        return B;
    }
}

数组左移k位 (不使用额外的空间)

数据结构——数组的循环右移K位算法,仅使用一个附加的空间,交换次数或元素移动时间复杂度为O(n)

数组的循环右移K位算法,仅使用一个附加的空间,交换次数或元素移动时间复杂度为O(n);
/*步骤分为三步:(K=2)

1.将第 1 位至第 N-K 位进行反转;1,2,3, 4,5->3,2,1, 4,5
2.将第 N-K+1 位至第 N 位进行反转;3,2,1, 4,5->3,2,1, 5,4
3.将整个第 1 位至第 N 位进行反转;3,2,1,5,4->4,5,1,2,3

最终即可实现 循环右移 K 位的算法;*/

void Exchange(int Num,int k,int* B)//生成函数
{
    k=k%Num;
    Reverse(0, Num - k - 1, B);//注意传参时一维数组下标由0开始
    Reverse(Num-k, Num-1, B);
    Reverse(0, Num - 1, B);
}

void Reverse(int start, int end, int* B)//逆置函数
{
    int i = start, j = end, temp = 0;//附加空间
    while (i < j)
    {
        temp = B[i];
        B[i] = B[j];
        B[j] = temp;
        j--;
        i++;
    }
}

数据结构——数组的循环右移K位算法,仅使用一个附加的空间,交换次数或元素移动时间复杂度为O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值