【算法入门级训练】- DAY 1

数组篇



前言

本次算法入门训练主要训练以下三个内容:

  1. 以特殊数据结构为载体的算法结构,比如:数组、链表、栈、二叉树等
  2. 以考察常见算法思想基础的算法题,比如:动态规划、贪心、回溯等
  3. 基于某种场景包装下的1和2

提示:以下是本篇文章正文内容

内容

第一题:二维数组中的查找

解题思路:这题的主要思路就是观察题目的特性,要注意到右上角和左下角位置的特殊性,排除这里的元素就可以排除一列或者一行。(查找的本质就是排除,相比于一个一个排除,显然一次排除一堆效率更高)
OJ链接:第一题

import java.util.ArrayList;
public class Solution {
    public boolean Find(int target, ArrayList<ArrayList<Integer>> array) {
        //二维数组的右上角是当前列的最小值,当前行的最大值
        //左下角是当前列的最大值,当前行的最小值
        //始终定位右上角
        int i = 0;
        int j = array.get(0).size() - 1;
        while(i < array.size() && j >= 0){
            if(array.get(i).get(j) > target){
                //说明当前列中没有目标值
                //排除掉当前列
                j--;
            }else if (array.get(i).get(j) < target){
                //说明当前行没有目标值
                //排除掉当前行
                i++;
            }else{
                //找到了
                return true;
            }
        }
        //没找到
        return false;
    }
}

第二题:旋转数组的最小数字

解题思路:方法一,遍历一次即可,旋转之后的数组有两段非递减序列,但是他们相交的地方是递减的只需要找到递减数字就是最小值。方法二,二分查找,定义首尾下标,因为是非递减数组旋转,所以旋转最后可以看做成两部分,前半部分整体非递减,后半部分整体非递减,前半部分整体大于后半部分。然后确定中间位置,中间位置要么在前半部分要么在后半部分,再前半部分范围就向后缩小,在后半部分就向前缩小。
OJ链接:第二题

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(ArrayList<Integer> array) {
        //旋转后数组分为两部分,两部分都是非递减序列
        if (array == null || array.size() == 0) {
            return 0;
        }
        int left = 0;
        int right = array.size() - 1;
        int mid = 0;
        while (array.get(left) >= array.get(right)) {
            //结束条件 当left和right相邻时,right就是最小值
            if (right - left == 1) {
                mid = right;
                break;
            }
            mid = (left + right) >> 1;
            //据题意可能出现array[mid] == array[left] == array[right],这时就直接线性探测
            if (array.get(mid) == array.get(left) && array.get(left) == array.get(right)) {
                int result = array.get(left);
                for (int i = left + 1; i < right; i++) {
                    if (result > array.get(i)) {
                        result = array.get(i);
                    }
                }
                return result;
            }
            //当mid在前半部分时,说明array[mid] > array[left],最小值在后半部分,范围向后缩小
            //当mid在后半部分时,说明array[mid] < array[left],最小值在前半部分,范围向前缩小
            if (array.get(mid) >= array.get(left)) {
                left = mid;
            } else {
                right = mid;
            }
        }
        return array.get(mid);
    }
}

第三题:调整数组顺序使奇数位于偶数前面

解题思路:找到奇数,如果奇数前有偶数,保存奇数再把奇数前的偶数全部往后移位给奇数腾出位置。
OJ链接:第三题

import java.util.*;
public class Solution {
    public void reOrderArray(int[] array) {
        int k = 0;
        for(int i = 0; i < array.length; i++){
            if((array[i] & 1) == 1){
                //奇数
                //保存它的值和位置
                int tmp = array[i];
                int j = i;
                //当前奇数和奇数序列之间有偶数就把所有偶数向后移
                while(j > k){
                    array[j] = array[j-1];
                    j--;
                }
                array[k++] = tmp;
            }
        }
    }
}

第四题:数组中出现次数超过一半的数字

解题思路:方法一,给数组排序,那么中间位置一定就是那个超过一半的数字。方法二,定义map统计数字出现的次数。方法三,每次删掉两个不同的元素,最后剩下的两个元素或者一个元素就是次数超过一半的数字,得到数字需要进行验证,可能出现没有这个数字的情况。
OJ链接:第四题

import java.util.*;
public class Solution {
    public int MoreThanHalfNum_Solution(ArrayList<Integer> array) {
        //每次删掉两个不同的元素的,最后剩下的两个元素或者一个元素就是次数超过一半的数字
        //得到数字需要进行验证,可能出现没有这个数字的情况
        //拿出第一个数字进行比较,如果该数字被删掉了,后续上来的第一个数字进行补充
        int times = 1;//被比较数字的个数
        int target = array.get(0);//被其它数字比较的数字
        for(int i = 1; i < array.size(); i++){
            //times = 0 说明被比较的数字被删掉了,需要更新数字
            if(times == 0){
                target = array.get(i);
                times = 1;
            }
            if(array.get(i) != target){
                times--;
            }else{
                times++;
            }
        }
        //进行验证
        times = 0;
        for(int i = 0; i < array.size(); i++){
            if(array.get(i) == target){
                times++;
            }
        }
        return times > array.size() / 2 ? target : 0;
    }
}

总结

以上就是今天训练的内容,今天的题除了第二题稍微有一点难度其它的都挺好写的,数组是题量最多的一种算法结构了,需要多多练习。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值