数据结构与算法

1、快排算法

解析链接:https://blog.csdn.net/qq_36186690/article/details/82470451

https://blog.csdn.net/TesuZer/article/details/80969006

整体思想:

通过排序将待排记录分割成独立的两部分,其中一部分记录的关键字比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列的目的。

0、如果最左边萝卜的下标>=最右右边萝卜下标,结束。(这就是我们的递归出口)
1、把第一个萝卜挖出来备用。
2、找两个工人一个叫A一个叫B,分别站在第一个萝卜(注意第一个萝卜的坑已经空了)和最后一个萝卜的位置。
3、如果A和B相遇了,则执行6,否则继续执行4和5
4、B往左走寻找比挖出来的第一个萝卜轻,且位置在A右边的萝卜,找到了就挖出来放到左所在的空坑里(这时B守着空坑)
5、由于B把A的坑用掉了,所以A要往右寻找比一个萝卜重,且位置在B左边的萝卜,找到了就挖出来放到B守着的空坑里(这时A又守空坑了),执行3
6、这时候两人已经相遇了,我们曾经把第一个萝卜挖出来,所以这时候必定有一个位置是空着的,这个位置也必然是他们相遇的这个位置,为什么呢?因为A和B相遇有两种情况,A往右走,与遇到B和B往左走遇到A,A和B的工作其实就是找到合适的萝卜去填对方的坑,当有一方在走,另一方所在位置必然是空的,所以A遇到B时候B是空的,B遇到A的时候A时是空的,所以最后的空坑肯定是他们相遇的位置。这时候只要把我们挖出的第一个萝卜放入这个空坑,就可以达到一个效果那就是相遇位置放上第一个萝卜之后,它左边的萝卜质量都小于它,它右边位置的萝卜质量都大于它。这时候就执行步骤7。
7、把所有萝卜分成两堆,[第一个萝卜,相遇位置]为第一堆,[相遇位置+1,第最后一个萝卜]为第二堆。对这两堆萝卜从步骤0开始执同样的操作。

package com.company;
import java.util.Arrays;

public class Main {
    private static int count;
    public static void main(String[] args) {
        int[] num = {3,45,78,64,52,11,64,55,99,11,18};
        System.out.println(arrayToString(num,"未排序"));
        QuickSort(num,0,num.length-1);
        System.out.println(arrayToString(num,"排序"));
        System.out.println("数组个数:"+num.length);
        System.out.println("循环次数:"+count);
    }

    /**
     * 快速排序
     * @param num	排序的数组
     * @param left	数组的前针
     * @param right 数组后针
     */

    private static void QuickSort(int[] num, int left, int right) {
        //如果left等于right,即数组只有一个元素,直接返回
        if(left>=right) {
            return;
        }
        //设置最左边的元素为基准值
        int key=num[left];
        //数组中比key小的放在左边,比key大的放在右边,key值下标为i
        int i=left;
        int j=right;
        while(i<j){
            //j向左移,直到遇到比key小的值
            while(num[j]>=key && i<j){
                j--;
            }
            //i向右移,直到遇到比key大的值
            while(num[i]<=key && i<j){
                i++;
            }
            //i和j指向的元素交换
            if(i<j){
                int temp=num[i];
                num[i]=num[j];
                num[j]=temp;
            }
        }
        num[left]=num[i];
        num[i]=key;
        count++;
        QuickSort(num,left,i-1);
        QuickSort(num,i+1,right);
    }

    /**
     * 将一个int类型数组转化为字符串
     * @param arr
     * @param flag
     * @return
     */

    private static String arrayToString(int[] arr,String flag) {
        String str = "数组为("+flag+"):";
        for(int a : arr) {
            str += a + "\t";
        }
        return str;
    }
}

2、二叉树根先序排列推算中序排列

整体思想:利用栈的特点,将先序看成入栈过程,中序看成出栈过程,推算出出栈的可能性

先序遍历:DCAGFEB

中序遍历可能性:CDFGEAB CGAFDEB DCGAFEB ACGDEFB

3、青蛙跳台阶(斐波那契数列)

题目描述:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法

思路:得到n个台阶,一共可以跳多少个2步,这个也是一个斐波那契数列的一个应用。对于本题前提只有一次跳一阶,和跳两阶。如果两种跳法,1阶或者2阶,那么假定第一次跳的是一阶,那么剩下的是n-1个台阶,跳法是f(n - 1)假定第一次跳的是2阶,那么剩下的是n-2个台阶,跳法是f(n - 2)那么这个时候就能够得到总的跳法为 f(n) = f(n - 1) + f(n - 2),然后这个出口就是:只有一阶的时候f(1) = 1, 只有两阶的时候f(2) = 2;

递归实现:效率比较差

 public int JumpFloor(int target) {       
       if(target == 1){
            return 1;
        }
        if(target == 2){
            return 2;
        }
        //第一次有两种选择,然后根据不同的选择,然后开始不同的下一步,但是下一步还是一样有两种选择
        return JumpFloor(target - 1) + JumpFloor(target - 2);

}

非递归实现:

public int JumpFloor(int target) {
        int x=1, y=2, z;
        if(target == 1){
            return 1;
        }
        if(target == 2){
            return 2;
        }
        for(int i = 3; i <= target; i ++){
            z = y;
            y = x + y;
            x = z;
        }
        return y;
	}

青蛙跳升级版

题目描述:一只青蛙一次可以跳上1级台阶,也可以跳上2级,。。。,它也可以跳上n级,求该青蛙跳上一个n级的台阶总共有多少种方法?

解答:也可以用逆推的思路去想,跳n级台阶,可以从n-1级跳上来,也可以从n-2级跳上来,从n-3级跳上来,依次下去,从第1级跳上去,或直接跳上去,所以,跳n级台阶的方法数相当于其它所有台阶数的方法的总和再加上从0级跳上去,表达式为 f(n) = f(n-1) + f(n-2) +…+ f(2) + f(1) + 1。例如:
当跳1级台阶时,f(1) = 1;
当跳2级台阶时,f(2) = f(1) + 1 = 2;
当跳3级台阶时,f(3) = f(2) + f(1) + 1 = 4;
当跳4级台阶时,f(4) = f(3) + f(2) + f(1) + 1 = 8;
。。。。。。。。。。。。。。。。。。。。。
f(n) = f(n-1) + f(n-2) +…+ f(2) + f(1) + 1
f(n-1) = f(n-2) +…+ f(2) + f(1) + 1
===》》 f(n) - f(n-1) = f(n-1) ===》》f(n) = 2 * f(n-1)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q0UlfUdi-1569810790971)(D:\常用代码\青蛙跳升级版.jpg)]

用n个2*1的小矩形无重叠2*n的大矩形

我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。总共有多少种方法?

类似于青蛙跳台阶,当n=1时,只有一种横向排列的方式。当n等于二时,22有两种选择,横向或者是竖向。当n等于3的时候对于23来说,如果选择的是竖向排列,则剩下的就是22排列,如果选择的是横向,则对于2n剩下的则只有1*n的一种选择。所以依次类推,找到迭代RectCover(target-1)+RectCover(target-2)。

public class Solution {
    public int RectCover(inttarget){
        if(target<=0){
            return0;
    }elseif(target==1||target == 2){
             returntarget;
    }
     return(RectCover(target-1)+RectCover(target-2));
    }
}

4、对年龄进行排序

使用常量大小的辅助空间,要求时间效率为O(n)。

import java.util.Arrays;

public class AgeSort {
    public static void main(String[] args) {
        int[] ages = new int[] { 23, 45, 32, 43, 21, 24, 25, 23, 22, 22, 21 };
        System.out.println("原数组为:" + Arrays.toString(ages));
        AgeSort as = new AgeSort();
        as.sortAge(ages);
        System.out.println("排序后的数组为:" + Arrays.toString(ages));
    }
    
    private void sortAge(int[] ages) {
        if (ages == null || ages.length < 1) {
            return;
        }
        int oldAge = 80;
        int youngAge = 20;
        // 初始化一个odlAge+1的数组
        int[] timeOfAge = new int[oldAge + 1];
        // 将数组元素都置为0
        for (int i = 0; i < timeOfAge.length; i++) {
            timeOfAge[i] = 0;
        }
        // 某个年龄出现了多少次,就在timeOfAge数组对应年龄的位置设置多少次
        for (int j = 0; j < ages.length; j++) {
            int a = ages[j];
            timeOfAge[a]++;
        }
        int index = 0;
        for (int i = youngAge; i <= oldAge; i++) {// 按照年龄从小到大依次遍历timeOfAge
            for (int j = 0; j < timeOfAge[i]; j++) {// 在timeOfAge中取得各个年龄位置记录的出现次数
                ages[index] = i;// 将新数组从头设置出现的年龄,已经排好序
                index++;
            }
        }
    }
}

5、int和Integer,valueOf和new String

import java.util.*;

public class test {
     public static void main(String[] arg){
        int i1=1;
        Integer i2=1;
        Integer i3=new Integer(1);
        Integer i4=Integer.valueOf(1);
        Integer i5=Integer.valueOf(1);
        System.out.println(i1==i2);
        System.out.println(i2==i3);
        System.out.println(i2==i4);
        System.out.println(i3==i4);
        System.out.println(i4==i5);
        String s1=new String("");
        String s2="";
        String s3="";
        String s4=String.valueOf("");
        String s5=String.valueOf("");
        System.out.println(s1==s2);
        System.out.println(s1==s4);
        System.out.println(s2==s3);
        System.out.println(s2==s4);
        System.out.println(s4==s5);
    }
}
true
false
true
false
true
false
false
true
true
true

int和Integer的区别:https://www.cnblogs.com/guodongdidi/p/6953217.html

String和String.valueOf: https://www.cnblogs.com/aspirant/p/9193112.html

​ https://www.cnblogs.com/aademeng/articles/10870164.html

6、java读取键盘输入

在nextInt(),next(),nextDouble(),nextFloat()方法与nextLine()连用并放在nextLine()前面时,就会出现如下错误:nextLine()并未读取任何输入,直接转到了下一行。

System.out.println("请输入矩阵的行数:");
int rows = scanner.nextInt();

System.out.println("请输入一个矩阵字符串,不包含空格:");
String tmp = scanner.nextLine();

System.out.println("请输入矩阵的列数:");
int cols = scanner.nextInt();

System.out.println("请输入要查询的字符串:");
String str = scanner.nextLine();
scanner.close(); 

在这里插入图片描述

问题分析:

​ nextLine()会把nextInt(),next(),nextDouble(),nextFloat()的结束换行符作为字符串读入,进而不需要从键盘输入字符串nextLine便已经转向了下一条语句执行。

解决办法:

​ 在每一个nextInt(),next(),nextDouble(),nextFloat()后都加一个nextLine()语句,将被next()去掉的Enter过滤掉。

![java读取键盘输入2](D:\常用代码\java读取键盘输入2.png)System.out.println("请输入矩阵的行数:");
int rows = scanner.nextInt();
scanner.nextLine();

System.out.println("请输入一个矩阵字符串,不包含空格:");
String tmp = scanner.nextLine();

System.out.println("请输入矩阵的列数:");
int cols = scanner.nextInt();
scanner.nextLine();

System.out.println("请输入要查询的字符串:");
String str = scanner.nextLine();

scanner.close();

//SolutionMethod2 solution2 = new SolutionMethod2();
System.out.println("矩阵中是否包含该字符串:");  

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值