数据结构-数组题总结

1. 二维数组中的查找

在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
主要思路:利用二维数组的有序性,定向地搜索。

public class Solution {
    public boolean Find(int target, int [][] array) {
        int rows = array.length;
        int columns = array[0].length;
        // 从左下角开始遍历
        int i = rows-1; 
        int j = 0;
        while(i>=0&&j<columns)
        {    
            int current = array[i][j];
            // 如果找到该数字就返回
            if(current == target) return true;
            // 如果当前数字小于目标数,则往右寻找
            else if(current < target) j++;
            // 反之则往上找
            else  i--;
        }
        return false;
    }
}

2. 调整数组的顺序,使得奇数在偶数前面

思路: 统计奇数的个数,然后开辟一个新的数组。一个偶数指针一个奇数指针

public class Solution {
    public void reOrderArray(int [] array) {
        int len = array.length;
        int oddCount = 0;
        int oddStart = 0;
        int[] newArray = new int[len];
        for(int i=0; i<len; i++){
            if(array[i]%2==1) oddCount++;
        }
        for(int i=0; i<len; i++){
            if(array[i]%2==1) newArray[oddStart++] = array[i];
            else newArray[oddCount++] = array[i];
        }
        for(int i=0; i<len; i++){
            array[i] = newArray[i];
        }
    }

}
// 冒泡的思想
public class Solution {
    public void reOrderArray(int [] array) {
        int i = 0 ;
        int n = array.length;
        while(i<n){
            if(array[i]%2 == 1){
                int pre = i-1;
                while(pre>=0&&array[pre]%2==0){
                    int temp = array[pre];
                    array[pre] = array[pre+1];
                    array[pre+1] = temp;
                    pre-- ;
                }
            }
            i++;
        }
    }

}

3. 最小的K个数

思想:
解法一:
a. We can use heap sorting to solve this problem. First of all, we need to push the first K numbers into a heap. For each of the following numbers will be compared with the top element in the heap and if the top element is large than current number selected, it will be removed from the heap and current number will be pushed into the heap.
b. Secondly, After implementing those steps iteratively, The numbers left in the heap are definitely the smallest K numbers.
c. Finally, we just need to add those K elements to our array and return it.

import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Comparator;
public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> result = new ArrayList<>();
        // 特殊情况要考虑周全
        if(input==null||input.length==0||k==0||k>input.length) 
        {return result;}
        // 创建最大堆
        PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(k, new Comparator<Integer>(){
            @Override
            public int compare(Integer o1, Integer o2){
                return o2.compareTo(o1);
            }
        });
        // 将前k个数放到堆中
        for(int i=0; i<input.length; i++){
            if(maxHeap.size() != k ){
                maxHeap.offer(input[i]);
            }
            // 当根节点比当前数字大,则根节点出栈,当前数字入栈
            else if(maxHeap.peek()>input[i]){
                maxHeap.poll();
                maxHeap.offer(input[i]);
            }
        }
        //将堆中元素加到数组中
        for(int val: maxHeap){
            result.add(val);
        }
        return result;
    }

}

解法二:
快速选择法

class Solution {
    public int findKthLargest(int[] nums, int k) {
        // 换成第k大
        k = nums.length - k;
        int lo = 0;
        int hi = nums.length -1;
        while(lo<hi){
            int pivot = partition(nums, lo, hi);
            //当前找到的数在pivot位,并且是第pivot+1大的的数,则退出并返回
            if(k==pivot) break;
            else if(k<pivot) hi = pivot - 1;
            else lo = pivot + 1;
        }
        return nums[k];
    }

    private int partition(int[] nums, int lo, int hi){
        // pivot设为最左边的数
        int pivot = lo;
        int l = lo + 1;
        int r = hi;
        while(true){
            // r一开就检测过,所以不写等号
            // 找到左边比nums[pivot]大的数
            while(l<=hi&&nums[l]<=nums[pivot]){
                l++;
            }
            // 找到右边比nums[pivot]小的数
            while(r>=lo+1&&nums[r]>=nums[pivot]){
                r--;
            }
            // 只大于的话,还得多跑一步没用的
            if(l>=r) break;
            //交换找到的数
            else{
                exc(nums, l, r);
            }
        }
        //交换pivot和右边的数,pivot左边都是比它小的数
        exc(nums, pivot, r);
        return r;
    }

    private void exc(int[] a, int l, int r){
        final int tmp = a[l];
        a[l] = a[r];
        a[r] = tmp;

    }

}

4. 数组中出现次数超过一半的数字

思路:
a. 设置一个count 和 cur。如果有数字出现超过一半,那么他肯定在哨兵算法中最后的cur中。但cur中的数不一定是出现超过一半的数。
b.如果cur等于当前的数,计数加一。如果不等于,但是count等于0,等变换cur就行。如果count大于0,则count–;
c.最后再遍历一遍数组即可

public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        int count = 1;
        int n = array.length;
        int cur = array[0];
        for(int i=1; i<n; i++){
            if(cur==array[i]) count++;
            if(cur!=array[i]) {
                 if(count==0) cur = array[i];
                 else count--;
            }   
        }
       count = 0; 
       for(int j=0; j<n; j++){
           if(cur==array[j])
               count++;
       }
        if(count>n/2) return cur;
        else return 0;
    }
}

5. 把数组排成最小的数

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
public class Solution {
    public String PrintMinNumber(int [] numbers) {
        if(numbers == null || numbers.length == 0) return "";
        int length = numbers.length;
        String[] str = new String[length];
        StringBuilder sb = new StringBuilder();
        for(int i=0; i<length; i++){
            str[i] = String.valueOf(numbers[i]);
        }
        Arrays.sort(str, new Comparator<String>(){
            @Override
            public int compare(String s1, String s2){
                //如果我在前小于它,那么就小于
                String c1 = s1 + s2;
                String c2 = s2 + s1;
                //如果c1小于c2,返回负数可以变成升序,也就是小的数在前的组合
                return c1.compareTo(c2);}
        });
        for(int i=0; i<length; i++){
            sb.append(str[i]);
        }

        return sb.toString();
    }
}

6.数组中的逆序对

public class Solution {
    public int InversePairs(int [] array) {
        // 首先排除特殊情况
        //进去递归,返回递归的结果
        //递归中停止条件是,Left==right
        //然后是左右递归,并保存左右递归的值
        //开始合并,确定两个指标都从末尾开始
        //如果左指针所指的值大于右指针所指的值,则左放入,同时可以确定有j-mid个数不符合条件
        //反之直接放进去
        //把剩下的元素放进去
        //然后把排好的复制到原来的当中
        if(array.length==0||array==null) return 0;
        int count = mergeSort(array, 0, array.length-1);
        return count;
    }

    private int mergeSort(int[] array, int left, int right){
        if(left>=right) return 0;
        int mid = (right+left)/2;
        int leftCount = mergeSort(array, left, mid);
        int rightCount = mergeSort(array, mid+1, right);
        int i = mid;
        int j = right;
        int k = right-left;
        int[] temp = new int[right-left+1];
        int count = 0;
        while(i>=left&&j>mid){
            if(array[i]>array[j]){
                count += j-mid;
                temp[k--] = array[i--];
                if(count >= 1000000007)
                    count %= 1000000007;
            }
            else{
                temp[k--] = array[j--];
            }
        }

        while(i>=left){
            temp[k] = array[i];
            i--;
            k--;
        }

        while(j>mid){
            temp[k--] = array[j--];
        }

        for(int v=0; v<right-left+1; v++){
            array[left+v] = temp[v];
        }

        return (leftCount + rightCount + count)%1000000007;
    }
}

7.数组中只出现一次的数字

思想: 最重要的步骤是得到两个不同的数字异或后的结果,然后要想办法拆开。

//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        if(array==null||array.length<2)
            return;
        int temp = 0;
        for(int i=0; i<array.length; i++){
            temp ^= array[i];
        }

        int indexOf1 = findFirstBitls(temp);
        for(int i=0; i<array.length; i++){
            if(isBit(array[i], indexOf1))
                num1[0] ^= array[i];
            else
                num2[0] ^= array[i];
        }
    }

    public int findFirstBitls(int num){
        int indexBit = 0;
        // 从右往左找第一位为1的数字
        while(((num&1)==0)&&(indexBit)<8*4){
            num = num >> 1;
            ++indexBit;
        }
        return indexBit;
    }

    public boolean isBit(int num, int indexBit){
        num = num>>indexBit;
        return(num & 1) == 1;
    }
}

8. 和为S的连续正数序

import java.util.ArrayList;
public class Solution {
    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {   //sh
        int l = 1;
        int r = 2;
        int totalSum = 3;
        int mid = (sum+1)/2;
        ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
        while(l<mid){
            if(sum==totalSum){
                ArrayList<Integer> subList = new ArrayList<>();
                for(int i=l; i<=r; i++){
                    subList.add(i);
                }
                ret.add(subList);
            }
            if(sum<totalSum){
                totalSum -= l;
                l++;
            }
            else{
                r++;
                totalSum += r;
            }
        }
        return ret;
    }
}

动态规划题目

1. 连续子数组最大和

主要思想:
a. O(n) time complexity. We need to store two states. One is used for recording the current largest sum of subsets and the other is used for recording the possible largest sum of subsets.
b. At every step, we upgrade both values. The possible largest sum is equal to the large one between the current value and the sum of the current value and the previous sum. The current largest sum depends on the large one between the previous largest sum and current possible sum.

public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {
        int n = array.length;
        int sumLast = array[0];
        int sumTotal = array[0];
        for(int i=1; i<n; i++){

            sumTotal = Math.max(array[i], array[i]+sumTotal);
            sumLast =  Math.max(sumLast, sumTotal);    

        }
        return sumLast;

    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值