剑指offer26-28

第26题
题目描述:输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

输入描述:输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

分析:
方法一:递归
在这里插入图片描述如上图所示,分为abc和abb演示,分别代表没有重复和有重复的情况。
代码如下:

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class Solution {
    public ArrayList<String> Permutation(String str) {
       ArrayList list = new ArrayList<String>();
       if(str!=null && str.length()>0){
           PermutationHelper(str.toCharArray(),0,list);
           Collections.sort(list);
       }
       return list;
    }
    //增强的方法
    public void PermutationHelper(char[] chars,int i,ArrayList<String> list){
        //递归结束的条件
        if(i == chars.length-1){
            list.add(String.valueOf(chars));
        }else{
             //用于校验当前需要交换的元素是否重复
            Set<Character> set = new HashSet<Character>();
            for(int j=i;j<chars.length;j++){
                
                if(!set.contains(chars[j])){
                    set.add(chars[j]);
                    swap(chars,i,j);
                    PermutationHelper(chars,i+1,list);
                    swap(chars,i,j);
                }
            }
        }
       
    }
    //交换数组两个位置的元素
    public void swap(char[] chars,int i,int j){
        char temp = chars[i];
        chars[i] = chars[j];
        chars[j] = temp;
    }
}

方法二:字典序法
如果知道字典序,这道题的解也非常简单,也不用考虑是否有重复的情况。定义如下:
在这里插入图片描述故代码如下:

//字典序法就全排列
    public ArrayList<String> Permutation2(String str){
        ArrayList<String> list = new ArrayList<>();
        //判断传入参数是否合法
        if(str == null || str.length()<=0){
            return list;
        }
        //字符串转为数组
        char[] chars = str.toCharArray();
        //对数组内的内容排序
        Arrays.sort(chars);
        //将第一个序列加到list中(数组转为字符串)
        list.add(Arrays.toString(chars));
        int len = chars.length;
        while(true){
            int leftIndex = len -1;
            int rightIndex ;
            /**
             *   find:  j=max {i | Pi < Pi+1 }
             *          k=max {i | Pi > Pj }
             */
            while(leftIndex>=1 && chars[leftIndex-1]>=chars[leftIndex]){
                leftIndex--;
            }
            //此时leftIndex==0则没有下一个序列,跳出循环
            if(leftIndex == 0)
                break;

            rightIndex = leftIndex ;
            while(rightIndex<len && chars[rightIndex]>chars[leftIndex-1]){
                rightIndex++;
            }
            swap(chars,leftIndex-1,rightIndex-1);
            reverse(chars,leftIndex);
            list.add(Arrays.toString(chars));
        }
        return list;
    }


    //倒置序列
    private void reverse(char[] chars,int k){
        if(chars==null || chars.length<=k)
            return;
        int len = chars.length;
        for(int i=0;i<(len-k)/2;i++){
            int m = k+i;
            int n = len-1-i;
            if(m<=n){
                swap(chars,m,n);
            }
        }
    }

    //交换数组两个位置的元素
    public void swap(char[] chars,int i,int j){
        char temp = chars[i];
        chars[i] = chars[j];
        chars[j] = temp;
    }

第二十七题:
题目描述:
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

分析:
首先要处理数组,第一反应就是先排个序,上述数组变为{1,2,2,2,2,2,3,4,5}。
然后计算一下数组的一半是多少。
假如长度是10,则至少需要10/2+1=6个数字。
假如长度是9,则至少需要9/2+1=5个数字。(计算机中做除法不会保留小数部分)
故我们需要至少连续出现 数组长度/2 + 1 个相同的数,题目中说有一个这样的数,所有找到一个这样的数我们就可以直接返回。
代码如下:

import java.util.Arrays;
public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        
        if(array.length == 1){
            return array[0];
        }
        
        int len = (array.length/2)+1;
        //对数组进行排序
        Arrays.sort(array);
        int value = 0;
        int count = 1;
        
        for(int i=0;i<array.length-1;i++){
            if(array[i] == array[i+1]){
                count++;
                if(count>=len){
                    return value;
                }
            }else{
                count = 1;
                value = array[i+1];
            }
        }
        return 0;
    }
}

第二十八题:
题目描述:
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

过于简单,不再分析。

原创文章 16 获赞 11 访问量 345

猜你喜欢

转载自blog.csdn.net/qq_38041105/article/details/105665710