文章目录

  • 浦发银行笔试真题
  • 1、判断素数
  • 2、判断闰年
  • 3、判断是否为非完全平方数
  • 4、异位词
  • 5、字符替换
  • 6、求字符串所有子串
  • 7、字符串大小写转换
  • 8、输出字符串中仅出现一次的第一个字符
  • 9、两个字符串,在第一个字符串中出现,第二个中未出现的字符串
  • 10、子串在字符串中出现的次数
  • 11、输出字符串简称
  • 12、字符串移除奇数位置字符
  • 13、字符串括号匹配问题
  • 14、字符串反转输出问题
  • 15、去掉字符串末尾的空格
  • 16、判定一个字符串中大小写字母、空格及特殊字符的出现次数
  • 17、输入两组字符串,判断第二组是否有和第一组重复的
  • 18、输出最大回文子串的长度
  • 19、判断给定字符串是不是IP地址
  • 20、按出现频率高低,给出字典序列
  • 21、查找最长公共前缀
  • 22、输入一个数字组成的字符串,再输入一个数字,数字代表在输入的字符串前面加0要达到的长度
  • 23、输入一个字符串,不同的单词用空格隔开,把这些单词的首字母取出并大写输出
  • 29、输出n的阶乘
  • 55、约瑟夫环问题
  • 56、排序算法
  • 1、冒泡排序
  • 2、选择排序
  • 3、插入排序
  • 4、快速排序
  • 5、堆排序


浦发银行笔试真题

1、判断素数

package com.elijih.banktests10;

import java.util.Scanner;

/**
 * 第一题
 * 判断素数:对于一个大于1的正整数,除了1和该数本身,没有其他因数的数称为素数
 * */
public class test01 {
    public static void main(String[] args) {
        System.out.print("请输入一个正整数:");
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        if (isPrime(num)){
            System.out.printf("%d是一个素数",num);
        }else{
            System.out.printf("%d不是素数",num);
        }
        sc.close();

    }

    public static boolean isPrime(int num){
        if(num<2){
            //不符合素数的定义
            return false;
        }
        int t = (int)Math.sqrt(num);
        for (int i=2;i<=t;i++){
            //当开平方的值小于2,必为素数,因为只有2和3满足条件
            if (num%i == 0){
                //当该数能够对i取模余0,说明还有其他因数
                return false;
            }
        }
        return true;
    }
}

2、判断闰年

package com.elijih.banktests10;
/**
 * 第二题:
 * 判断闰年
 * 输出从1990年到2010年之间的闰年
 *
 * 闰年:①、普通年能被4整除且不能被100整除的为闰年。(如2004年就是闰年,1901年不是闰年)
 * ②、世纪年能被400整除的是闰年。(如2000年是闰年,1900年不是闰年)
 * */
public class test02 {
    public static void main(String[] args) {
        for (int year=1990;year<=2010;year++){
            if(year%4 == 0 && year%100 != 0){
                System.out.printf("%d是闰年\n",year);
                continue;
            }else if (year%100 == 0 && year%400 == 0 ){
                System.out.printf("%d是闰年\n",year);
            }
        }
    }
}

3、判断是否为非完全平方数

package com.elijih.banktests10;

import java.util.Scanner;
import java.util.regex.Pattern;

/**
 * 第三题
 * 判断是否为非完全平方数
 *
 * 非完全平方数:如果一个正整数 a 不是某一个整数 b 的平方,那么这个正整数 a 叫做非完全平方数
 * */
public class test03 {
    public static void main(String[] args) {
        Scanner sc =new Scanner(System.in);
        System.out.print("请输入一个数:");
        int num = 0;
        try {
            num = sc.nextInt();
        } catch (Exception e) {
            throw new RuntimeException("输入的不是整数");
        }
        if(!isNumric(num)){
            //先判断是不是正整数,再判断是不是完全平方数
            System.out.printf("%d不是一个正整数,更不是非完全平方数",num);
        }else if ((Math.sqrt(num) - (int)Math.sqrt(num)) == 0){
            System.out.printf("%d不是一个非完全平方数",num);
        }else{
            System.out.printf("%d是一个非完全平方数",num);
        }
        sc.close();
    }

    public static boolean isNumric(int num){
        Pattern p = Pattern.compile("[0-9]*");
        return p.matcher(Integer.toString(num)).matches();
    }

}

4、异位词

package com.elijih.banktests10;

import java.util.Arrays;
import java.util.Scanner;

/**
 * 第四题:
 * 判断两个字符串是否是异位,比如abcn和banc是一对,anc和nac是一对,两个字符串完全奇偶互换,则称为异位,
 * 判断两个字符串是否为异位词,意思是判断两个字符串有相同数量的字母,再对两个字符串进行排序,排序后相等则为异位词
 * */
public class test04 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入第一个字符串:");
        String str1 = sc.nextLine();
        System.out.print("请输入第二个字符串:");
        String str2 = sc.nextLine();

        if (isAnagram(str1,str2)){
            System.out.printf("%s和%s是一对异序字符串",str1,str2);
        }else {
            System.out.printf("%s和%s不是一对异序字符串",str1,str2);
        }

    }
    public static boolean isAnagram(String str1,String str2){
        if(str1.length() != str2.length()){
            return false;
        }
        char[] c1 = str1.toCharArray();
        char[] c2 = str2.toCharArray();
        Arrays.sort(c1);
        Arrays.sort(c2);
        return Arrays.equals(c1,c2);
    }
}

5、字符替换

package com.elijih.banktests10;

import java.util.Arrays;
import java.util.Scanner;

/**
 * 第五题
 * 字符串中字符替换,把字符串中的a和A换成c输出
 * */
public class test05 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入一个字符串:");
        String s = sc.nextLine();
        char[] t = s.toCharArray();
        for (int i=0;i<t.length;i++){
            if (t[i] == 'a' || t[i] == 'A'){
                t[i]='c';
            }
        }
        String str = new String(t);
        System.out.printf("转换后的字符串是%s",str);
        sc.close();
    }
}

6、求字符串所有子串

package com.elijih.banktests10;
/**
 * 第六题
 * 求字符串的所有子串
 * */
public class test06 {
    public static void main(String[] args) {
        String str = "abbcc";
        System.out.printf("原字符串为:%s\n",str);
        int count = 0;

        for (int i=0;i<str.length();i++){
            for(int j=i+1;j<=str.length();j++){
                count++;
                System.out.printf("第%d个子串为:%s\n",count,str.substring(i,j));
            }
        }
    }
}

7、字符串大小写转换

package com.elijih.banktests10;
/**
 * 第七题
 * 字符串大小写转换
 * */
public class test07 {
    public static void main(String[] args) {
        String str = "AFSGsbf";

        //大写转小写
        System.out.println(str.toLowerCase());

        //小写转大写
        System.out.println(str.toUpperCase());
    }
}

8、输出字符串中仅出现一次的第一个字符

package com.elijih.banktests10;

import java.util.HashMap;

/**
 * 第八题
 * 输出字符串中仅出现一次的第一个字符
 *
 * 思路:哈希表
 * */
public class test08 {
    public static void main(String[] args) {
        String str = "affasf";

        HashMap<Character,Integer> hashMap = new HashMap<>();

        //遍历字符串,把每个字符存储在哈希表里
        for (int i=0;i<str.length();i++){
            if (hashMap.containsKey(str.charAt(i))){
                //如果包含有当前字符,value+1
                int value = hashMap.get(str.charAt(i));
                hashMap.put(str.charAt(i),value+1);
            }else{
                //不包含,value置为1
                hashMap.put(str.charAt(i),1);
            }
        }

        //再次遍历字符串,看每个字符出现的次数
        for(int i=0;i<str.length();i++){
            if(hashMap.get(str.charAt(i)) == 1){
                System.out.println(str.charAt(i));
                break;
            }
        }

    }
}

9、两个字符串,在第一个字符串中出现,第二个中未出现的字符串

package com.elijih.banktests10;

import java.util.Arrays;
import java.util.HashMap;

/**
 * 第九题
 * 给出A,B两个字符串,求在第一个字符串出现,但第二个字符串中未出现,重复出现时只取第一次出现,输出字符串
 *
 * !!! 题看不懂,什么东西 !!!
 * */
public class test09 {
    public static void main(String[] args) {
        String A = "asdfgh";
        String B = "asdcvvbcvb";

        HashMap<Character,Integer> hashMap = new HashMap<>();

        //先把A的每个字符加入哈希表存储
        for (int i=0;i<A.length();i++){

        }

        
    }

}

10、子串在字符串中出现的次数

package com.elijih.banktests10;
/**
 * 第十题
 * 给定一个字符串,一个子串,判定子串在该字符串中出现的次数
 *
 * */
public class test10 {
    public static void main(String[] args) {
        String big = "aaaasssdddaaasssddddaaaasssdddd";
        String small = "as";
        System.out.println(count(big,small));
    }

    public static int count(String big,String small){
        //来一个计数器
        int count = 0;
        //思路:遍历大串,遍历到出现小串的首字母时,在大串中截取小串长度的字符,判断和小串是否一样
        //
        //char[] charBig = big.toCharArray();
        for(int i=0;i<big.length();i++){
            if (big.charAt(i) == small.charAt(0) && big.substring(i,i+(small.length())).equals(small)){
                //字符串比较得用equals
                    count++;
            }
        }

        return count;
    }
}

11、输出字符串简称

package com.elijih.banktests20;
/**
 * 第十一题
 * 输出字符串简称,例如字符串是"end of file",输出”EOF"
 *以空格为界限,遍历出每一个token,再取出每一个token的首字母,并大写,拼接输出
 * */
public class Test01 {
    public static void main(String[] args) {
        String line = "end of file";
        System.out.println(transAka(line));

    }

    public static String transAka(String line){
        int len = line.length();
        StringBuffer aka = new StringBuffer();

        for (int i=0;i<len;i++){
            if( (i==0 || line.charAt(i-1) == ' ') && line.charAt(i) != ' '){
                aka.append(line.charAt(i));

            }

        }
        return aka.toString().toUpperCase();
    }
}

12、字符串移除奇数位置字符

package com.elijih.banktests20;
/**
 * 第十二题
 * 字符串移除奇数位置字符问题
 *
 * 把不是奇数位置的字符拼接成一个新的字符串
 * */
public class Test02 {
    public static void main(String[] args) {
        String line = "abcdefgh";
        change(line);
    }

    public static void change(String line){
        StringBuffer sb = new StringBuffer();
        for (int i=0;i<line.length();i++){
            if(i%2 == 0){
                sb.append(line.charAt(i));
            }
        }
        System.out.println(sb);
    }
}

13、字符串括号匹配问题

package com.elijih.banktests20;

import java.util.Stack;

/**
 * 第十三题
 * 字符串括号匹配问题
 *
 * 1.将字符串转换为字符数组chars
 * 2.利用for循环,将每一次读取到的字符chars[i]与(,[,{进行比较,若匹配,则将chars[i]压入栈中;否则,进入3.
 * 3.将chars[i]与),],}进行比较。这里以)为例进行说明,若chars[i]=’)’,则与栈顶元素top进行比较,若栈顶元素为’(’,则匹配,
 * 将栈顶元素pop出;若栈顶元素不为‘(’,则不匹配,返回false,退出循环
 * 4.当所有chars[i]都遍历完成,退出循环,返回true,证明括号全部匹配
 * */
public class Test03 {
    public static void main(String[] args) {
        String line = "4684(){(}[]";
        isMatch(line);
    }
    public static void isMatch(String line){
        Stack<Character> stack = new Stack<>();
        char[] chars = line.toCharArray();
        boolean flag = true;
        for (int i=0;i<line.length();i++){
            if(chars[i] == '(' || chars[i] == '[' || chars[i] == '{'){
                stack.push(chars[i]);
            }
            if ((chars[i] == ')' && stack.peek() == '(') || (chars[i] == ']' && stack.peek() == '[') ||
                    chars[i] == '}' && stack.peek() == '{'){
                stack.pop();
            }else if((chars[i] == ')' && stack.peek() != '(') || (chars[i] == ']' && stack.peek() != '[') ||
                    chars[i] == '}' && stack.peek() != '{'){
                flag = false;
                break;
            }
        }

        if (!stack.isEmpty()){
            flag = false;
        }
        if (flag){
            System.out.println("匹配");
        }else {
            System.out.println("不匹配");
        }
    }
}

14、字符串反转输出问题

package com.elijih.banktests20;

import java.util.Stack;

/**
 * 第十四题
 * 字符串反转输出问题
 *
 * 这种题太多了
 * 来一道:给定字符串s,要求把s中多于一个的连续空格压缩成一个空格,并将剩下的连续的非空字符串倒叙打印出来
 * 例如:给定”abc  def  efg",输出"cba fed gfe"
 *
 * 思路:用栈的思想来做
 * */
public class Test04 {
    public static void main(String[] args) {
        String s = "abc  def  efg";
        reversePrint(s);
    }

    public static void reversePrint(String s){
        Stack<Character> stack = new Stack<>();
        StringBuffer sb = new StringBuffer();
        int i = 0;
        int len = s.length();
        while (i<len){
            //存
            while (i<len && s.charAt(i)!=' '){

                stack.push(s.charAt(i));
                i++;
            }
            //取
            while (!stack.isEmpty()){
                sb.append(stack.pop());
            }
            boolean flag = false;
            while(i<len && s.charAt(i) == ' '){
                i++;
                flag = true;
            }
            if(flag){
                sb.append(' ');
                flag = false;
            }
        }

        System.out.println(sb);
    }

    public static boolean isStr(char c){
        if(c>97 && c<122){
            return true;
        }
        return false;
    }
}

15、去掉字符串末尾的空格

package com.elijih.banktests20;
/**
 * 第十五题
 * 去掉字符串末尾的空格
 *
 * */
public class Test05 {
    public static void main(String[] args) {
        String s = "   di di   ";
        System.out.println("去掉字符串末尾的空格后:"+trimEnd(s));
        System.out.println("去掉字符串开头的空格后:"+trimStart(s));
    }
    public static String trimEnd(String s){
        if (s == null){
            return null;
        }
        return s.replaceAll("\\s+$","");
    }

    public static String trimStart(String s){
        if (s == null){
            return null;
        }
        return s.replaceAll("^\\s+","");
    }


}

16、判定一个字符串中大小写字母、空格及特殊字符的出现次数

package com.elijih.banktests20;
/**
 * 第十六题
 * 判断一个字符串中数字、大小写字母、空格、以及特殊字符的数量并输出
 * */
public class Test06 {
    public static void main(String[] args) {
        String s = "sfsagqrgfUFYUFYG-*-++IG16462422     ";
        count(s);
    }
    public static void count(String s){
        int countNum = 0;
        int countSLetter = 0;
        int countBLetter = 0;
        int countSpace = 0;
        int countOther = 0;


        char[] chars = s.toCharArray();
        for (char c:chars
             ) {
            if (c>=97 && c<=122){
                countSLetter++;
            } else if (c>=65 && c<=90){
                countBLetter++;
            } else if (c>=48 && c<=57){
                countNum++;
            } else if (c == ' '){
                countSpace++;
            }else{
                countOther++;
            }
        }
        System.out.printf("该字符串中数字有%d个\n",countNum);
        System.out.printf("该字符串中小写字母有%d个\n",countSLetter);
        System.out.printf("该字符串中大写字母有%d个\n",countBLetter);
        System.out.printf("该字符串中空格有%d个\n",countSpace);
        System.out.printf("该字符串中其他字符有%d个\n",countOther);
    }
}

17、输入两组字符串,判断第二组是否有和第一组重复的

package com.elijih.banktests20;

import java.util.ArrayList;
import java.util.Scanner;

/**
 * 第十七题
 * 输出一组字符串,再输入一组字符串,判断是否有与之前字符串一致,有则输出是第几个字符串与之前的字符串一致
 *
 *
 * 要点:Scanner的close方法要注意,最好在main中定义,拿到其他方法中使用,否则很容易出现noSuchElementException
 * */
public class Test07 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Scanner sc2 = new Scanner(System.in);
        ArrayList<String> list1 = insert(sc,sc2);
        System.out.println("第一组字符串获取完毕");
        ArrayList<String> list2 = insert(sc,sc2);
        sc.close();
        sc2.close();

        compare(list1,list2);

    }
    public static ArrayList<String> insert(Scanner sc,Scanner sc2){

        System.out.print("请输入你想要输入的字符串个数:");
        int num = sc.nextInt();
        System.out.println("请输入字符串:");

        ArrayList<String> list = new ArrayList<>();
        while(num != 0){
            String line = sc2.nextLine();
            list.add(line);
            num--;
        }

        return list;

    }


    public static void compare(ArrayList<String> list1,ArrayList<String> list2){
        for(int i=0;i<list1.size();i++){
            for (int j=0;j<list2.size();j++){
                if (list1.get(i).equals(list2.get(j))){
                    System.out.printf("有和第一组中第%d个字符串%s一致的,且一致的是第%d个\n",(i+1),list1.get(i),(j+1));
                }
            }
        }
    }
}

18、输出最大回文子串的长度

package com.elijih.banktests20;
/**
 * 第十八题
 * 输出字符串的最大回文子字符串的长度(输入一串字符串,判断里边是否有回文子串,如“12321”,有则输出其中最大的长度,
 * 如“211232109”,输出5
 *
 * 这里采用中心扩散法
 * 后续实现动态规划解法
 * */
public class Test08 {

    public static void main(String[] args) {
        System.out.println(getLongestManacher("abba"));
    }

    public static String getLongestManacher(String s){
        if(s == null || s.length()<1){
            return "";
        }
        int start=0,end=0;//开始的索引和结束的索引,先初始化为0
        for (int i=0;i<s.length();i++){
            int oddLen = expandAroundCenter(s,i,i);//探索的是回文子串为奇数位的情况
            int evenLen = expandAroundCenter(s,i,i+1);//探索的是回文子串位为偶数位的情况
            int len = Math.max(oddLen,evenLen);


            if(len>end-start){
                start = i-(len-1)/2;
                end = i+len/2;
            }
        }


        return s.substring(start,end+1);
    }

    public static int expandAroundCenter(String s,int left,int right){
        while (left>=0 && right<s.length() && s.charAt(left)==s.charAt(right)){
            --left;
            ++right;
        }
        return right - left - 1;
    }

}

19、判断给定字符串是不是IP地址

package com.elijih.banktests20;
/**
 * 第十九题
 * 判断给定字符串是不是ip地址
 * 判断地址是否合法,如128.211.11.2将字符串分为128 211 11 2四个整型变量,判断范围是否在0~255之间
 * 若有一个不合法,则为不合法
 * */
public class Test09 {
    public static void main(String[] args) {
        String s = "128.2111.21.2";
        if (isIp(s)){
            System.out.println("是IP地址");
        }else {
            System.out.println("不是IP地址");
        }
    }

    public static boolean isIp(String s){
        boolean flag = true;
        String[] ip = s.split("\\.");
        for (String num:ip
             ) {
            if (!(Integer.parseInt(num)<=255 && Integer.parseInt(num)>=0)){
                flag = false;
            }
        }

        return flag;
    }
}

20、按出现频率高低,给出字典序列

package com.elijih.banktests20;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 第二十题
 * 按出现频率高低输出字母,给出字典序列aaabbbbassd
 *
 * 思路:首先根据 s 构造 HashMap,键值对中的键就是 s[i],值就是 s[i] 出现的次数。
 * 然后我们构造一个桶的集合,意思就是集合里的每个元素都是一个桶。我们维护第 i 个桶中存放 s 中出现次数为 i 的字符。
 * 从后往前遍历这个桶的集合,并填充要返回的数组 res 即可。

 * */
public class Test10 {
    public static void main(String[] args) {
        System.out.println(frequencySort("abbcccdddd"));
    }
    public static String frequencySort(String s){
        //1.先把数据存放在map里
        HashMap<Character,Integer> map = new HashMap<>();

        for (char c:s.toCharArray()
             ) {
            map.put(c,map.getOrDefault(c,0)+1);
        }

        //2.实现桶结构
        ArrayList<Character>[] buckets = new ArrayList[s.length()+1];
        //搞这么多桶的目的是为了把出现频次为i的字符放到第i个桶里

        for (char key:map.keySet()
             ) {
            int value = map.get(key);
            //每个字符出现的频次就是这个value,value是多少就放到哪个桶里
            if (buckets[value] == null){
                //需要被放进去的桶,得先初始化
                buckets[value] = new ArrayList<>();
            }
            buckets[value].add(key);//把字符放进集合里
        }

        //3.倒序取出桶里的字符
        StringBuilder res = new StringBuilder();
        for (int i=buckets.length-1;i>0;i--){
            //遍历所有的桶
            if(buckets[i] != null){
                for (char c:buckets[i]
                     ) {
                    //获取桶里的元素
                    for (int j=0;j<i;j++){
                        //每一个字符出现多少次,就添加多少次
                        res.append(c);
                    }

                }
            }
        }
        return res.toString();
    }




}

21、查找最长公共前缀

package com.elijih.banktests30;
/**
 * 第二十一题
 * 编写一个函数来查找字符串数组中的最长公共前缀,若不存在公共前缀,返回空字符串“”
 *
 *
 * 思路:纵向扫描
 * 以字符数组的第一个为基准,依次扫描其他字符串的每一列,如果有一个字符串的当前列字符对不上,那么就直接退出循环
 * */
public class Test01 {
    public static void main(String[] args) {
        String[] strs = new String[]{"asd","asdfg","asdwe"};
        System.out.println(longestCommonPrefix(strs));
    }
    public static String longestCommonPrefix(String[] strs){
        if (strs == null || strs.length == 0){
            return "";
        }
        int len = strs[0].length();//获取第一个字符串的长度
        int count = strs.length;//获取字符数组有几个字符串

        for (int i=0;i<strs.length;i++){
            char c = strs[0].charAt(i);//获取第一个字符串的每一列
            for (int j=1;j<count;j++){
                if (strs[j].charAt(i) != c || strs[j].length() == i){
                    //当其他字符串的这一列的字符和第一个字符串的c不相同,或者当其他字符串已经被遍历完了
                    return strs[0].substring(0,i);

                }
            }
        }

        return strs[0];
    }
}

22、输入一个数字组成的字符串,再输入一个数字,数字代表在输入的字符串前面加0要达到的长度

package com.elijih.banktests30;

import java.util.Scanner;

/**
 * 第二十二道
 * 输入一个数字组成的字符串,再输入一个数字,数字代表在输入的字符串前面加0要达到的长度,
 * 例如输入字符串23,输入8,则输出就是00000023
 *
 * */
public class Test02 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入一个字符串:");
        String line = sc.nextLine();
        System.out.print("请输入一个数字:");
        int num = sc.nextInt();
        System.out.println("处理结果为:"+appends(line, num));
    }
    public static String appends(String s,int num){
        StringBuilder sb = new StringBuilder();
        if (num<=0){
            System.out.println(s);
        }
        for (int i=0;i<num;i++){
            sb.append("0");
        }
        sb.append(s);

        return sb.toString();
    }
}

23、输入一个字符串,不同的单词用空格隔开,把这些单词的首字母取出并大写输出

package com.elijih.banktests30;

import java.util.ArrayList;
import java.util.Iterator;

import java.util.Scanner;


/**
 * 第二十三题
 * 输入一个字符串,不同的单词用空格隔开,把这些单词的首字母取出并大写输出,如输入hello world,输入HW,
 * 请实现多行输入的输出,输入0则停止继续输入
 *
 * */
public class Test03 {
    public static void main(String[] args) {

        System.out.printf("请输入要输入的字符串,输入0结束\n");

        String s = "";
        ArrayList<String> list = new ArrayList<>();
        Scanner sc = new Scanner(System.in);
        while(!s.equals("0")){

            s =sc.next();
            if (!s.equals("0")){
                list.add(s);
            }

        }
        sc.close();

        StringBuilder sb = new StringBuilder();
        Iterator it = list.iterator();
        while(it.hasNext()){
            sb.append(it.next()+" ");
        }
        System.out.println(getInitial(sb.toString()));

    }
    public static String getInitial(String s){
        String[] strs = s.split("\\s");
        StringBuilder sb = new StringBuilder();
        for (int i=0;i<strs.length;i++){
            sb.append(strs[i].charAt(0));
        }

        return sb.toString().toUpperCase();
    }
}

29、输出n的阶乘

package com.elijih.part05_recursion;
/**
 * 递归
 * 阶乘的实现
 * */
public class FactorialDemo {
    public static void main(String[] args) {
        Factorial f = new Factorial();
        System.out.println(f.factorial(3));
    }
}

class Factorial{
    public int factorial(int n){
        if(n == 1){
            return 1;
        }else {
            return factorial(n-1)*n;
        }
    }
}
/*
* 6
 * */

55、约瑟夫环问题

package com.elijih.part02_linkedlist;

public class JosepfuDemo {
    public static void main(String[] args) {
        //测
        CircleLinkedList circleLinkedList = new CircleLinkedList();
        circleLinkedList.add(125);
        circleLinkedList.showLinkedList();
        circleLinkedList.Josepfu(10,20,125);
    }
}

/**
 * 创建一个唤醒链表类,管理节点
 * */
class CircleLinkedList{
    /**
     * 先创建一个first节点,不赋值
     * */
    private Boy first = null;
    /**
     * 添加小孩节点,构建环形链表
     * nums为小孩数量
     * */
    public void add(int nums){
        //对nums需要做一个校验,因为至少一个节点才能构成环形链表
        if (nums<1){
            System.out.println("nums的数值不对,无法完成环形链表");
            return;
        }

        //使用辅助指针来帮助构建环形链表
        Boy curBoy = null;
        for (int i=1;i<=nums;i++){
            //先处理第一个节点的情况
            if(i == 1){
                Boy boy = new Boy(1);
                first = boy;
                first.setNext(first);
                curBoy=first;
                continue;
            }
            //开始插入节点
            Boy boy = new Boy(i);
            curBoy.setNext(boy);
            boy.setNext(first);
            curBoy = boy;
        }
        //System.out.println(first.getId());
    }
    /**
     * 解决约瑟夫问题
     * startId:开始报数的孩子
     * countNum:报数次数
     * nums:孩子总数
     * */
    public void Josepfu(int startId,int countNum,int nums){
        //先校验数据
        if(startId < 1 || startId > nums || first == null){
            System.out.println("参数有误");
            return;
        }


        //两个指针

        /*Boy helper = new Boy(nums);
        * 不能这样做,原因是链表已经用add方法建立,这样做是新建一个节点,和原先的链表没有关系,所以会出现空指针异常
        * */

        Boy helper = first;
        /*while (true){
            if(helper.getNext() == first){
                break;
            }
            helper = helper.getNext();
        }*/

        for (int i=0;i<nums-1;i++){
            helper=helper.getNext();
        }
        System.out.println(helper.getId());

        //移动指针到准备开始报数小孩的位置
        for (int j=0;j<startId-1;j++){
            System.out.println("-----");
            first = first.getNext();
            helper = helper.getNext();
        }
        //开始处理
        while (true){
            if (helper == first){
                //说明遍历完毕
                System.out.println("*********");
                break;
            }
            for (int j=0;j<countNum-1;j++){
                first=first.getNext();
                helper=helper.getNext();
            }
            System.out.printf("第%d个小孩出列\n",first.getId());
            first=first.getNext();
            helper.setNext(first);
        }
        System.out.printf("最后一个出圈的小孩id是%d",first.getId());
    }

    /**
     * 展示类,用来展示创建的链表,即遍历链表
     * */
    public void showLinkedList(){
        //先判读链表是否为空
        if(first == null){
            System.out.println("链表为空");
            return;
        }
        //辅助指针帮助遍历
        Boy curBoy = first;
        while (true){
            System.out.printf("第%d个小孩 \n",curBoy.getId());
            if (curBoy.getNext() == first){
                break;
            }
            curBoy = curBoy.getNext();
        }
    }

}


/**
 * 创建一个节点类,模拟小孩/
 */

class Boy{
    private int id;
    private Boy next;

    public Boy(int id){
        this.id = id;
    }
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Boy getNext() {
        return next;
    }

    public void setNext(Boy next) {
        this.next = next;
    }
}

56、排序算法

1、冒泡排序

package com.elijih.part06_sort;

import java.util.Arrays;

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

        //定义一个中间变量
        int temp=0;
        //定义一个表示符,来判断在某次循环中,是否有元素发生交换
        boolean flag = false;
        //外层for循环表示总共排序的次数
        for (int i=0;i<arr.length-1;i++){
            //内层for循环是每次排序的具体运作,每一次排序都会把当前最大的那个数据挪到最后,所以每次都比上一次少管一个数
            for(int j=0;j<arr.length-1-i;j++){
                if (arr[j]>arr[j+1]){
                    flag = true;//表示进入了这次循环,下次继续循环
                    temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
            System.out.printf("第%d次排序的结果是%s\n",i+1, Arrays.toString(arr));
            if (!flag){
                //此时表示这次循环里,没有元素发生移动,已经排序好了
                break;
            }else {
                flag = false;//这里需要将flag重置,否则flag就一直是true了,判断就会失效
            }

        }
    }
}

2、选择排序

package com.elijih.part06_sort;

import java.util.Arrays;

/**
 * 选择排序
 * */
public class Demo02_SelectSort {
    public static void main(String[] args) {
        int[] arr = new int[]{19,-1,6,37,2};
        selectSort(arr);
    }

    public static void selectSort(int[] arr){

        //外层循环表示循环的次数
        for (int i=0;i<arr.length-1;i++){
            //内层循环是每次对数组进行的操作
            int min = arr[i];
            int minIndex = i;
            for (int j=i+1;j<arr.length;j++){

                if (min > arr[j]){
                    //说明此时的最小值不是最小的
                    min = arr[j];
                    minIndex = j;
                }
            }
            //操作一轮后,已经找到了最小值和最小值的索引,此事交换两个值的位置
            if (minIndex != i){
                arr[minIndex] = arr[i];
                arr[i] = min;
            }
        }
        //循环结束后,排序成功,此时输出结果
        System.out.println(Arrays.toString(arr));
    }
}

3、插入排序

package com.elijih.part06_sort;

import java.util.Arrays;

public class Demo03_InsertSort {
    public static void main(String[] args) {
        int[] arr = {3,6,1,-5,-50};
        insertSort(arr);
    }
    public static void insertSort(int[] arr){
        //定义外层循环,外层循环仍旧是操作的次数,但是这里从1开始,是因为操作的对象是无序表中的数据
        for (int i=1;i<arr.length;i++){
            //内层循环,是具体的操作内容
            //先定义一个待插入的值
            int insertVal = arr[i];
            //定义一个待插入的下标,最先考虑的是待插入值下标的前一位
            int insertIndex = i-1;

            while(insertIndex >= 0 && insertVal < arr[insertIndex]){
                //若满足条件,则说明待插入的值比待插入索引所指向的值要小,所以待插入索引指向的值需要往后移一位,把位置空出来
                arr[insertIndex+1] = arr[insertIndex];
                insertIndex--;//自减,继续往前判断
            }

            //当退出循环时,说明要插入的位置已经找到
            arr[insertIndex+1] = insertVal;

            System.out.printf("第%d次排序的结果是%s:",i, Arrays.toString(arr));
            System.out.println();
        }
    }
}

4、快速排序

package com.elijih.part06_sort;

import java.util.Arrays;
/**
 * 以最左边数为基准值的快速排序
 * 思路:
 * 1.先把最左边的值确定为基准值,然后将他取出,则他的索引所指向的空间空出来
 * 2.定义两个指针,一个从最右边的数值开始遍历(j),一个从最左边开始遍历(i)
 * 3.当j遍历到比基准值小的数据时,停下,并把该数据放入上次空出的空间里(第一次为基准值所在的位置)
 * 4.轮到i走,当i遍历到比基准值大的数据时,停下来,把i所指向的数据放进上次空出来的空间里
 * 5.当i=j时,遍历结束,把基准值放入此时空着的空间里,此时就完成了第一趟排序,基准值左边的数据都比它小,右边的数据都比它大
 * 6.向左递归,向右递归,此时需要注意i和j的大小需要调整,j需要左移,i需要右移
 * */
public class Demo04_QuickSort02 {
    public static void main(String[] args) {
        int [] arr = {51,22,83,46,75,18,68,30};
        quicksort2(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }

    public static void quicksort2(int[] arr ,int left ,int right){
        int i = left;//左指针
        int j= right;//右指针

        int stand = arr[left];//基准值,始终以最左边的值为基准

        while (i<j){
            /*if (i>=j){
                break;
            }*/
            while(i<j && arr[j]>stand){
                j--;
            }
            arr[i] = arr[j];
            while (i<j && arr[i]<stand){
                i++;
            }
            arr[j] = arr[i];
        }
        arr[i] = stand;

        //递归调用
        /*if (i==j){
            i++;
            j--;
        }*/

        //向左递归
        if (j>left){
            quicksort2(arr,left,j-1);
        }

        //向右递归
        if (i<right){
            quicksort2(arr,i+1,right);
        }

    }
}

5、堆排序

package com.elijih.part08_tree;

import java.util.Arrays;

/**
 * 堆排序
 */
public class Demo02_HeapSort {
    public static void main(String[] args) {
        int [] arr = {5,6,7,11,5,12,3,60,1};

        heapSort(arr);

    }


    public static void heapSort(int[] arr){
        int temp = 0;
        for (int i=arr.length/2-1;i>=0;i--){
            //从最后一个非叶子结点开始,遍历所有的非叶子节点
            adjustHeap(arr,i,arr.length);
        }
        System.out.println(Arrays.toString(arr));
        for (int j = arr.length-1;j>0;j--){
            //遍历所有的元素,从后往前遍历
            //交换第一个元素和最后一个元素
            temp = arr[j];
            arr[j]=arr[0];
            arr[0] = temp;
            //直接对第一个元素进行调整,调整后当前最大的值就会出现在第一个元素的位置上
            adjustHeap(arr,0,j);
        }
        System.out.println(Arrays.toString(arr));
    }

    public static void adjustHeap(int[] arr,int i,int length){
        //先保存一下这个非叶子节点的值
        int temp = arr[i];
        //i指向非叶子结点,k指向该节点的左叶子节点
        for (int k=2*i+1;k<length;k=2*k+1){
            if (k+1 < length && arr[k]<arr[k+1]){
                //如果这个小树的右叶子节点比左叶子节点大,那就让k指向右叶子节点,谁大谁就和父节点比
                k++;
            }
            if (arr[k]>temp){
                /**
                 * 最关键的地方在这里了!!!!困扰了一天的!!!!
                 * k所指向的值一直在和temp相比,而非i所指向的值!!!!!
                 * */
                //如果比较之后,父节点比较小,那就把大的值赋给父节点
                arr[i] = arr[k];
                i = k;
                //arr[i] = temp;
                // 这里交不交换都可以,结果一样,不交换是为了提高性能,因为这个方法的目的是为了从二叉树里找到最大的一个数好把他放在末尾,所以不交换就可以用
                //刚刚找到的这个比较大的数字,继续再和下边的数字比较一手,看有没有比自己大的,没有那无所谓
            }else{
                break;
            }
        }
        arr[i] = temp;

        //System.out.println(Arrays.toString(arr));这一句测试用的
    }
}