剑指offer 数组专题 刷题记录(4)

剑指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)

上一篇:剑指offer 数组专题 刷题记录(3)


下一篇:剑指offer 数组专题 刷题记录(2)