算法基础技巧(一)

1. 基础知识

1.1 输入数组以引用的方式作为方法的参数

在这里插入图片描述

2.算法基础技巧

2.1 双指针算法(原地算法)技巧

双指针又称为快慢指针
在这里插入图片描述
使用双指针可以使不用新建一个数组,从而使这道题的时间复杂度从O(n)降低到O(1)

在这里插入图片描述

class Solution {
    public void moveZeroes(int[] nums) {
        if(nums == null || nums.length == 0){
            return;
        }

        int i = 0 ; 
        int j = 0 ;

        for(;i < nums.length ; i++){
            if(nums[i] != 0){
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
                j++;
            }
        }
    }
}

优化写法:不交换两个元素,直接赋值

class Solution {
    public void moveZeroes(int[] nums) {
        if(nums == null || nums.length == 0){
            return;
        }

        int i = 0 ; 
        int j = 0 ;

        for(;i < nums.length ; i++){
            if(nums[i] != 0){
                if(i != j){
                    nums[j] = nums[i];
                }
                j++;
            }
        }

        for(; j < nums.length; j++){
            nums[j] = 0;
        }
    }
}

2.2 双指针编程技巧(对撞指针)

在这里插入图片描述

class Solution {
    public void reverseString(char[] s) {

        int head = 0;
        int tail = s.length - 1;

        while(head != tail && tail > head){
            char temp = s[head];
            s[head] = s[tail];
            s[tail] = temp;

            head++;
            tail--;
        }
    }
}

在这里插入图片描述
在这里插入图片描述

class Solution {
    public boolean isPalindrome(String s) {
        StringBuffer sgood = new StringBuffer();
        int length = s.length();
        for (int i = 0; i < length; i++) {
            char ch = s.charAt(i);
            if (Character.isLetterOrDigit(ch)) {
                sgood.append(Character.toLowerCase(ch));
            }
        }
        int n = sgood.length();
        int left = 0, right = n - 1;
        while (left < right) {
            if (Character.toLowerCase(sgood.charAt(left)) != Character.toLowerCase(sgood.charAt(right))) {
                return false;
            }
            ++left;
            --right;
        }
        return true;
    }
}

2.3 递归

方法自身不能无限制的调用自身,否则会出现栈溢出的情况。需要有一个限制条件来退出递归

递归的特点
1、大问题可以拆分为小问题,将小问题解决了,大问题也就解决了
2、每一个子问题的解决的方法逻辑是一样的
3、一定要有递归终止条件

写递归代码分两步

  1. 写出递推公式 f(n) = f(n -1) + f(n-2);
  2. 写出递归终止条件:f(1) = 1 ; f(2) = 2;

不用纠结与细节,写出上面的两步,递归代码基本也就写完了
爬楼梯问题:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution {
    public int fib(int n) {
        if(n < 2){
            return n;
        }
        int leftFib = fib(n - 1);
        int rightFib = fib(n - 2);
        return leftFib + rightFib;
    }
}

2 排序算法

2.1 排序算法基础知识

升序排序(默认)
降序排序

  1. 排序算法的稳定性
  2. 何为原地排序算法

在这里插入图片描述
在这里插入图片描述

2.2 冒泡排序

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
冒泡排序代码实现

public static void main(String[] args) {
        int[] arr = new int[]{4,2,5,1,6,9};

        for(int i = 1 ; i <= arr.length; i++){ // 控制冒泡轮数
            int time = arr.length - i;
            for(int j = 0 ; j < time ;j++){ // 控制每轮比较次数
                if(arr[j] > arr[j+1]){
                    int temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
        for(int i = 0 ; i < arr.length ; i++){
            System.out.println(arr[i]);
        }
    }

在这里插入图片描述
在这里插入图片描述

2.3 选择排序

选择排序是将数组中最小的元素找到,并放到数组的第一个位置,
接下来在找剩下元素最小的元素,放到第二个位置

在这里插入图片描述
代码实现

public static void selectSort(int[] arr){
        if(arr == null || arr.length == 0){
            return ;
        }
        for(int i = 0 ; i < arr.length; i++){
            int minIndex = i;
            for(int j = i + 1; j < arr.length ;j++){
                if(arr[j] < arr[minIndex]){
                    minIndex = j;
                }
            }
            int temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
    }

在这里插入图片描述

2.4 插入排序

将元素插入到已经有序的数组当中(第一步的时候,我们假设第一个元素是有序的即可)
在这里插入图片描述

在这里插入图片描述
代码实现

public static void insertSort(int arr[]){
        // i 没必要从0开始,因为第一个元素假设他有序
        for(int i =1;i < arr.length ; i++){
            for(int j = i ; j > 0 ; j--){
                if(arr[j] < arr[j-1]){
                    int temp = arr[j];
                    arr[j] = arr[j-1];
                    arr[j-1] = temp;
                }else{
                    //如果当前元素比前一个元素还要大
                    //那就没必要在往前比较了
                    break;
                }
            }
        }
    }

在这里插入图片描述

优化后的插入排序

public static void insertSort(int arr[]){
        // i 没必要从0开始,因为第一个元素假设他有序
        for(int i =1;i < arr.length ; i++){
            int temp = arr[i];
            int j;
            for(j = i ; j > 0 ; j--){
                if(j != 0){
                    if(temp < arr[j-1]){
                        arr[j] = arr[j-1];
                    }else{
                        //如果当前元素比前一个元素还要大
                        //那就没必要在往前比较了
                        break;
                    }
                }
            }
            arr[j] = temp;
        }
    }

2.5 冒泡、选择、插入排序的比较

性能高到低

插入(用的最多的)> 选择(不是稳定性算法) > 冒泡

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值