【第一题】重新排列字符串
分析:
方法一:直接按照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;
}
}