【Leecode笔记】第十八周上(1.4-1.5)排序专题

【第一题】重新排列字符串

在这里插入图片描述
分析:
方法一:直接按照indices数组中的顺序将其存入新数组即可;
方法二:哈希表,存储字符及字符顺序的映射关系。

class Solution {
    public String restoreString(String s, int[] indices) {
        char[] ret = new char[s.length()];
        for(int i = 0;i < indices.length;i++){
            ret[indices[i]] = s.charAt(i); 
            //System.out.println(ret[indices[i]]);
        }
        return new String(ret);
    }
}
//哈希表(不是吧阿sir,哈希表这么慢吗
//执行用时:4 ms, 在所有 Java 提交中击败了18.72% 的用户
//内存消耗:38.8 MB, 在所有 Java 提交中击败了32.05% 的用户
class Solution {
    public String restoreString(String s, int[] indices) {
        if(s.length() == 1 ||s.length() == 0){return s;}
        Map<Integer,Character> map = new HashMap<>();
        StringBuffer buf = new StringBuffer();
        for(int i = 0;i < s.length();i++){
            map.put(indices[i],s.charAt(i));
        }
        for(int i = 0;i< s.length();i++){
            buf.append(map.get(i));
        }
        return buf.toString();
    }
}

【第二题】判断能否形成等差数列

在这里插入图片描述

分析:首先排序,然后计算前后两项的差,比较是否每次前后两项的差为定值。

//执行用时:1 ms, 在所有 Java 提交中击败了99.56% 的用户
//内存消耗:38.1 MB, 在所有 Java 提交中击败了49.08% 的用户
class Solution {
    public boolean canMakeArithmeticProgression(int[] arr) {
        if(arr.length == 2){return true;}
        Arrays.sort(arr);
        int i = 0,j = 1;
        int cha = arr[j] - arr[i];
        while(j < arr.length){
            if(arr[j] - arr[i] == cha){
                i++;
                j++;
            }else{
                return false;
            }
        }
        return true;
    }
}

【第三题】数组的相对排序

在这里插入图片描述

分析:

方法一:建立哈希表,遍历arr1,存放arr1中的元素和其出现次数的映射关系,然后遍历arr2,进行map的get操作
方法二:不用哈希表,改用桶数组,思路一样。

注意!!未出现在arr2中的元素,要按照升序,因此事先要对arr1进行排序。

//执行用时:2 ms, 在所有 Java 提交中击败了54.90% 的用户
//内存消耗:38.4 MB, 在所有 Java 提交中击败了71.19% 的用户
class Solution {
    public int[] relativeSortArray(int[] arr1, int[] arr2) {
        if(arr1.length == arr2.length && arr1.length == 1){return arr1;}
        Map<Integer,Integer> map = new HashMap<>();
        int[] ret = new int[arr1.length];
        int k = 0;
        Arrays.sort(arr1);
        for(int i = 0;i < arr1.length;i++){
            map.put(arr1[i],map.getOrDefault(arr1[i],0)+1);
        }
        while(k < ret.length){
            for(int i = 0;i < arr2.length;i++){
                for(int j = 0;j < map.get(arr2[i]);j++){
                    ret[k++] = arr2[i]; 
                }
                map.put(arr2[i],-1);
            }
            for(int a = 0;a < arr1.length;a++){
                if(map.get(arr1[a])!=-1){
                    ret[k++] = arr1[a];
                }
            }
        }
        return ret;
    }
}
//执行用时:0 ms, 在所有 Java 提交中击败了100.00% 的用户
//内存消耗:38.5 MB, 在所有 Java 提交中击败了56.07% 的用户
public int[] relativeSortArray(int[] arr1, int[] arr2) {
	int[] nums = new int[1001];
	int[] res = new int[arr1.length];
	//遍历arr1,统计每个元素的数量
	for(int i: arr1){
		nums[i]++;
	}
	//遍历arr2,统计arr2中出现的元素
	int index= 0;
	for(int i :arr2){
		while(nums[i] > 0){
			res[index++] = i;
			nums[i]--;
		}
	}
	//遍历nums,处理剩下arr2中未出现的元素
	for(int i = 0;i < nums.length;i++){
		while(nums[i] > 0){
			res[index++] = i;
			nums[i]--;
		}
	}
	return res;
}

【第四题】三角形的最长周长

在这里插入图片描述

分析:首先将其排序,然后从后边开始遍历,满足两边之和大于第三边,两边之差小于第三边即可。
在这里插入图片描述

//执行用时:9 ms, 在所有 Java 提交中击败了62.52% 的用户
//内存消耗:38.7 MB, 在所有 Java 提交中击败了94.13% 的用户
class Solution {
    public int largestPerimeter(int[] A) {
	    if(A == null || A.length < 3){
	            return 0;
	    }
        Arrays.sort(A);
        for(int i = A.length - 1;i >=2;i--){
            int a = A[i];
            int b = A[i-1];
            int c = A[i-2];
            if(a < b+c){
                return a+b+c;
            }
        }
        return 0;
    }
}

【第五题】按奇偶排序数组II

在这里插入图片描述

分析:也就是说,将奇数放在奇数位,将偶数放在偶数位。
直接双指针,i指向偶数位,j指向奇数位,假如i指向的数是奇数,j指向偶数,则两者交换;假如其中一个指向的不是该指的,那么它停住,另一个走两步;假如指向的没错,那么两者都往前走两步。

方法二:交换下标。

//执行用时:4 ms, 在所有 Java 提交中击败了31.91% 的用户
//内存消耗:39.8 MB, 在所有 Java 提交中击败了56.70% 的用户
class Solution {
    public int[] sortArrayByParityII(int[] A) {
        int i = 0,j = 1;
        if(A.length == 2&&A[i] % 2!=0 && A[j] % 2==0){
                int temp = A[i];
                A[i] = A[j];
                A[j] = temp;
                return A;
        }
        if(A.length == 2&&A[i] % 2==0 && A[j] % 2!=0){
                return A;
        }
        while(i < A.length && j < A.length){
            if(A[i] % 2!=0 && A[j] % 2==0){
                int temp = A[i];
                A[i] = A[j];
                A[j] = temp;
                i+=2;
                j+=2;
            }
            else if(A[i] %2 == 0 || A[j]%2 !=0){
                if(A[i]%2 == 0){
                    i+=2;
                }
                if(A[j] %2!=0){
                    j+=2;
                } 
            }
            //System.out.println(i+" "+j);
        }
        return A;
    }
}
//优化版
//执行用时:2 ms, 在所有 Java 提交中击败了99.98% 的用户
//内存消耗:39.3 MB, 在所有 Java 提交中击败了99.27% 的用户
class Solution{
    public int[] sortArrayByParityII(int[] A){
        int j = 1;
        //假如前A.length-1都有序,那么最后一个肯定有序,因为奇偶数量相等。
        for(int i = 0;i < A.length -1;i = i+2){
            if((A[i] & 1) !=0){
                while((A[j] & 1) !=0){
                    j = j+2;
                }
                int tmp = A[i];
                A[i] = A[j];
                A[j] = tmp;
            }
        }
        return A;
    }
}
//执行用时:3 ms, 在所有 Java 提交中击败了78.94% 的用户
//内存消耗:41 MB, 在所有 Java 提交中击败了41.36% 的用户
class Solution{
    public int[] sortArrayByParityII(int[] A){
        int[] result = new int[A.length];
        int ji = 1;
        int ou = 0;
        for(int i = 0;i < A.length;i++){
            if(A[i] % 2 == 0){
                result[ou] = A[i];
                ou+=2;
            }else{
                result[ji] = A[i];
                ji+=2;
            }
        }
        return result;
    }
}

【第六题】能否连接形成数组

在这里插入图片描述

分析:将arr排序,再将pieces按照pieces里的数组第一个元素大小排序,然后比较元素是否相等。

方法二:哈希表Map<Integer,int[]>,保存数组的行号和数组元素的对应关系。
在这里插入图片描述

//执行用时:1 ms, 在所有 Java 提交中击败了92.13% 的用户
//内存消耗:37.7 MB, 在所有 Java 提交中击败了73.88% 的用户
class Solution{
	public boolean canFormArray(int[] arr,int[][] pieces){
		Map<Integer,int[]> map = new HashMap<>();
		for(int[] piece:pieces){
			map.put(piece[0],piece);
		}
		for(int i = 0;i < arr.length;){
			if(!map.containsKey(arr[i])){
				return false;
			}
			int[] array = map.get(arr[i]);
			for(int j = 0;j < array.length;j++,i++){
				if(arr[i] !=array[j]){
					return false;
				}
			}
		}
		return true;
	}
}

【第七题】寻找比目标字母大的最小字母

在这里插入图片描述

分析:输出letters数组中第一个比target大的字母即可。字母是依序循环出现。(这是我刷过最简单的题了)

//执行用时:0 ms, 在所有 Java 提交中击败了100.00% 的用户
//内存消耗:38.7 MB, 在所有 Java 提交中击败了67.60% 的用户
class Solution {
    public char nextGreatestLetter(char[] letters, char target) {
        for(char c:letters){
            if(c > target){
                return c;
            }
        }
        return letters[0];
    }
}

【第八题】有效的字母异位词

在这里插入图片描述

分析:所谓的字母异位词,就是每个字母的个数都相等。
方法一:排序。
方法二:哈希表+哈希集。存放字母及其个数的映射,并保证元素的个数一样。

//执行用时:3 ms, 在所有 Java 提交中击败了84.31% 的用户
//内存消耗:38.5 MB, 在所有 Java 提交中击败了83.81% 的用户
class Solution{
    public boolean isAnagram(String s,String t){
        if(s.length()!=t.length()){return false;}
        char[] sChars = s.toCharArray();
        char[] tChars = t.toCharArray();
        Arrays.sort(sChars);
        Arrays.sort(tChars);
        return Arrays.equals(sChars,tChars);
    }
}

【第九题】去掉最低工资和最高工资后的工资平均值

在这里插入图片描述

分析:简单题重拳出击!

//执行用时:0 ms, 在所有 Java 提交中击败了100.00% 的用户
//内存消耗:35.9 MB, 在所有 Java 提交中击败了94.43% 的用户
class Solution {
    public double average(int[] salary) {
        double count = 0;
        double sum = 0;
        Arrays.sort(salary);
        for(int i = 1;i < salary.length-1;i++){
            sum +=salary[i];
            count++;
        }
        return sum/count;
    }
}

【第十题】根据数字二进制下1的数目排序

在这里插入图片描述

分析:原来还有bitCount的API

//其实就是用同一个数组元素,既存储了1的位数,又存储了arr[i]的值
//执行用时:3 ms, 在所有 Java 提交中击败了99.79% 的用户
//内存消耗:38.6 MB, 在所有 Java 提交中击败了90.73% 的用户
class Solution {
    public int[] sortByBits(int[] arr) {
        int[] map = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
        	//其实就是用同一个数组元素,既存储了1的位数,又存储了arr[i]的值,这样的话,假如位数相等,就按照arr[i]的大小排序,太妙了!!
            map[i] = Integer.bitCount(arr[i]) * 100000 + arr[i];
        }
        Arrays.sort(map);
        //还原map数组
        for (int i = 0; i < map.length; i++) {
            map[i] = map[i] % 100000;
        }
        return map;
    }
}
//直接重写数组排序方法
public int[] sortByBits(int[] arr) {
        Integer[] nums = new Integer[arr.length];
        for (int i = 0; i < arr.length; i++) {
            nums[i] = arr[i];
        }
        Arrays.sort(nums, (o1, o2) -> {
            int bitCountA = Integer.bitCount(o1);
            int bitCountB = Integer.bitCount(o2);
            // 相同按原数,不同按位数
            return bitCountA == bitCountB ? o1 - o2 : bitCountA - bitCountB;
        });
        for (int i = 0; i < arr.length; i++) {
            arr[i] = nums[i];
        }
        return arr;
    }
//方法三:手动统计1的个数
//执行用时:9 ms, 在所有 Java 提交中击败了65.43% 的用户
//内存消耗:38.8 MB, 在所有 Java 提交中击败了71.53% 的用户
class Solution {
    public int[] sortByBits(int[] arr) {
        List<Integer> list = new ArrayList<Integer>();
        for (int x : arr) {
            list.add(x);
        }
        int[] bit = new int[10001];
        for (int i = 1; i <= 10000; ++i) {
            bit[i] = bit[i >> 1] + (i & 1);
        }
        Collections.sort(list, new Comparator<Integer>() {
            public int compare(Integer x, Integer y) {
                if (bit[x] != bit[y]) {
                    return bit[x] - bit[y];
                } else {
                    return x - y;
                }
            }
        });
        for (int i = 0; i < arr.length; ++i) {
            arr[i] = list.get(i);
        }
        return arr;
    }
}


【第十一题】按照频率将数组升序排序

在这里插入图片描述

分析:

//对列表进行重写排序
class Solution {
    public int[] frequencySort(int[] nums) {
        Map<Integer,Integer> resMap = new HashMap<>();
        List<Integer> numsList = new ArrayList<>();
        //统计次数
        for(int cur :nums){
            numsList.add(cur);
            resMap.put(cur,resMap.getOrDefault(cur,0)+1);
        }
        //按照规则排序
        numsList.sort((a,b)->{
            int aCount = resMap.get(a);
            int bCount = resMap.get(b);
            if(aCount == bCount){
                return b-a;
            }
            return aCount - bCount;
        });
        return numsList.stream().mapToInt(Integer::intValue).toArray();
    }
}
//对数组进行重写排序
class Solution{
    public int[] frequencySort(int[] nums){
        int[][] arr = new int[nums.length][2];
        for(int i = 0;i < nums.length;i++){
            int count = 0;
            for(int j = 0;j < nums.length;j++){
                if(nums[j] == nums[i]){
                    count++;
                }
            }
            arr[i][0] = nums[i];
            arr[i][1] = count;
        }
        Arrays.sort(arr,new Comparator<int[]>(){
            public int compare(int[] o1,int[] o2){
                return o1[1] == o2[1]? o2[0]-o1[0] : o1[1]-o2[1];
            }
        });
        int[] res = new int[nums.length];
        for(int i = 0;i < arr.length;i++){
            res[i] = arr[i][0];
        }
        return res;
    }
}

【第十二题】非递增顺序的最小子序列

在这里插入图片描述

分析:首先降序,保证非递增。然后只要元素之和大于总和的一半,就可返回。

//执行用时:4 ms, 在所有 Java 提交中击败了92.79% 的用户
//内存消耗:38.5 MB, 在所有 Java 提交中击败了78.97% 的用户
class Solution {
    public List<Integer> minSubsequence(int[] nums) {
        ArrayList<Integer> list = new ArrayList<>();
        if(nums.length == 1){
            list.add(nums[0]);
            return list;
        }
        if(nums.length == 2){
            if(nums[0]!=nums[1]){
                list.add(Math.max(nums[0],nums[1]));
                return list;
            }else{
                list.add(nums[0]);
                list.add(nums[1]);
                return list;
            }
        }
        Arrays.sort(nums);
        //记录元素的总和
        double sum = 0;
        //记录当前累加的总和
        double total = nums[nums.length-1];
        for(int i = 0;i < nums.length;i++){
            sum+=nums[i];
        }
        if(nums[nums.length-1] > sum/2){
            list.add(nums[nums.length-1]);
            return list;
        }else{
            list.add(nums[nums.length-1]);
        }
        int i = nums.length-1;
        while(i >0){
            total+=nums[i-1];
            list.add(nums[i-1]);
            if(total > sum/2){
                return list;
            }
            i--;
        }
        return list;
    }
}

【第十三题】距离顺序排列矩阵单元格

在这里插入图片描述
分析:重写数组排序方法

//执行用时:16 ms, 在所有 Java 提交中击败了46.14% 的用户
//内存消耗:40.4 MB, 在所有 Java 提交中击败了75.35% 的用户
class Solution {
    public int[][] allCellsDistOrder(int R, int C, int r0, int c0) {
        int[][] res = new int[R*C][2];
        int index = 0;
        for(int i = 0;i < R;i++)
            for(int j = 0;j < C;j++){
                int[] xy = {i,j};
                res[index++] = xy;
            }
            Arrays.sort(res,new Comparator<int[]>(){
                public int compare(int[] o1,int[] o2){
                    int dis1 = Math.abs(o1[0]-r0) + Math.abs(o1[1]-c0);
                    int dis2 = Math.abs(o2[0]-r0) + Math.abs(o2[1]-c0);
                    return dis1 - dis2;
                }
            });
        return res;
    }
}

【第十四题】上升下降字符串

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值