Skip to content

Commit 045af2e

Browse files
committed
code
1 parent f9d18b3 commit 045af2e

File tree

3 files changed

+249
-0
lines changed

3 files changed

+249
-0
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
## 题目描述
2+
3+
给你一个整数数组 arr 。请你将数组中的元素按照其二进制表示中数字 1 的数目升序排序。
4+
5+
如果存在多个数字二进制中 1 的数目相同,则必须将它们按照数值大小升序排列。
6+
7+
请你返回排序后的数组。
8+
9+
**示例 1:**
10+
11+
```
12+
输入:arr = [0,1,2,3,4,5,6,7,8]
13+
输出:[0,1,2,4,8,3,5,6,7]
14+
解释:[0] 是唯一一个有 0 个 1 的数。
15+
[1,2,4,8] 都有 1 个 1 。
16+
[3,5,6] 有 2 个 1 。
17+
[7] 有 3 个 1 。
18+
按照 1 的个数排序得到的结果数组为 [0,1,2,4,8,3,5,6,7]
19+
```
20+
21+
**示例 2:**
22+
23+
```
24+
输入:arr = [1024,512,256,128,64,32,16,8,4,2,1]
25+
输出:[1,2,4,8,16,32,64,128,256,512,1024]
26+
解释:数组中所有整数二进制下都只有 1 个 1 ,所以你需要按照数值大小将它们排序。
27+
```
28+
29+
**示例 3:**
30+
31+
```
32+
输入:arr = [10000,10000]
33+
输出:[10000,10000]
34+
```
35+
36+
**示例 4:**
37+
38+
```
39+
输入:arr = [2,3,5,7,11,13,17,19]
40+
输出:[2,3,5,17,7,11,13,19]
41+
```
42+
43+
**示例 5:**
44+
45+
```
46+
输入:arr = [10,100,1000,10000]
47+
输出:[10,100,10000,1000]
48+
```
49+
50+
**提示:**
51+
52+
- 1 <= arr.length <= 500
53+
- 0 <= arr[i] <= 10^4
54+
55+
## 方法一:暴力
56+
57+
对每个十进制的数转二进制的时候统计二进制表示中的 1 的个数即可。
58+
59+
## 方法二:递推预处理
60+
我们定义 bit[i] 为数字 i 二进制表示下数字 1 的个数,则可以列出递推式:
61+
62+
bit[i]=bit[i>>1]+(i&1)
63+
64+
所以我们线性预处理 bitbit 数组然后去排序即可。
65+
66+
```
67+
class Solution {
68+
public int[] sortByBits(int[] arr) {
69+
List<Integer> list = new ArrayList<Integer>();
70+
for (int x : arr) {
71+
list.add(x);
72+
}
73+
int[] bit = new int[10001];
74+
for (int i = 1; i <= 10000; ++i) {
75+
bit[i] = bit[i >> 1] + (i & 1);
76+
}
77+
Collections.sort(list, new Comparator<Integer>() {
78+
public int compare(Integer x, Integer y) {
79+
if (bit[x] != bit[y]) {
80+
return bit[x] - bit[y];
81+
} else {
82+
return x - y;
83+
}
84+
}
85+
});
86+
for (int i = 0; i < arr.length; ++i) {
87+
arr[i] = list.get(i);
88+
}
89+
return arr;
90+
}
91+
}
92+
```
93+
94+
### 复杂度分析
95+
96+
- 时间复杂度:O(nlogn),其中 n 为整数数组 arr 的长度。
97+
98+
- 空间复杂度:O(n),其中 n 为整数数组 arr 的长度。
99+
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
## 题目描述
2+
3+
给你一个数字数组 arr 。
4+
5+
如果一个数列中,任意相邻两项的差总等于同一个常数,那么这个数列就称为 等差数列 。
6+
7+
如果可以重新排列数组形成等差数列,请返回 true ;否则,返回 false 。
8+
9+
10+
**示例 1:**
11+
12+
```
13+
输入:arr = [3,5,1]
14+
输出:true
15+
解释:对数组重新排序得到 [1,3,5] 或者 [5,3,1] ,任意相邻两项的差分别为 2 或 -2 ,可以形成等差数列。
16+
```
17+
18+
**示例 2:**
19+
20+
```
21+
输入:arr = [1,2,4]
22+
输出:false
23+
解释:无法通过重新排序得到等差数列。
24+
```
25+
26+
**提示:**
27+
28+
- 2 <= arr.length <= 1000
29+
- -10^6 <= arr[i] <= 10^6
30+
31+
## 方法一:模拟
32+
33+
首先我们对原序列排序,假设排序之后序列为{a0,a1,⋯an},如果对 i∈[1,n−1] 中的每个数都有 a_i x 2 = a_{i - 1} + a_{i + 1}成立,那么这个数列就是等差数列。
34+
35+
```
36+
class Solution {
37+
public boolean canMakeArithmeticProgression(int[] arr) {
38+
Arrays.sort(arr);
39+
for (int i = 1; i < arr.length - 1; ++i) {
40+
if (arr[i] * 2 != arr[i - 1] + arr[i + 1]) {
41+
return false;
42+
}
43+
}
44+
return true;
45+
}
46+
}
47+
```
48+
49+
### 复杂度分析
50+
51+
- 时间复杂度:O(nlogn)。排序的时间代价为 O(nlogn),遍历序列的时间代价是 O(n),故渐进时间复杂度为 O(nlogn+n)=O(nlogn)。
52+
- 空间复杂度:O(logn)。快速排序中使用的栈空间期望是 O(logn)。
53+
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
## 题目描述
2+
3+
给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。
4+
5+
对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。
6+
7+
你可以返回任何满足上述条件的数组作为答案。
8+
9+
 
10+
11+
**示例:**
12+
13+
```
14+
输入:[4,2,5,7]
15+
输出:[4,5,2,7]
16+
解释:[4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。
17+
```
18+
19+
**提示:**
20+
21+
- 2 <= A.length <= 20000
22+
- A.length % 2 == 0
23+
- 0 <= A[i] <= 1000
24+
25+
## 方法一: 两次遍历
26+
27+
遍历一遍数组把所有的偶数放进 ans[0],ans[2],ans[4],依次类推。
28+
29+
再遍历一遍数组把所有的奇数依次放进 ans[1],ans[3],ans[5],依次类推。
30+
31+
```
32+
class Solution {
33+
public int[] sortArrayByParityII(int[] A) {
34+
int n = A.length;
35+
int[] ans = new int[n];
36+
37+
int i = 0;
38+
for (int x : A) {
39+
if (x % 2 == 0) {
40+
ans[i] = x;
41+
i += 2;
42+
}
43+
}
44+
i = 1;
45+
for (int x : A) {
46+
if (x % 2 == 1) {
47+
ans[i] = x;
48+
i += 2;
49+
}
50+
}
51+
return ans;
52+
}
53+
}
54+
```
55+
56+
### 复杂度分析
57+
58+
- 时间复杂度:O(N),其中 N 是数组 A 的长度。
59+
60+
- 空间复杂度:O(1)。注意在这里我们不考虑输出数组的空间占用。
61+
62+
## 方法二: 双指针
63+
64+
如果原数组可以修改,则可以使用就地算法求解。
65+
66+
为数组的偶数下标部分和奇数下标部分分别维护指针 i,j。随后,在每一步中,如果A[i] 为奇数,则不断地向前移动 j(每次移动两个单位),直到遇见下一个偶数。此时,可以直接将 A[i] 与 A[j] 交换。我们不断进行这样的过程,最终能够将所有的整数放在正确的位置上。
67+
68+
```
69+
class Solution {
70+
public int[] sortArrayByParityII(int[] A) {
71+
int n = A.length;
72+
int j = 1;
73+
for (int i = 0; i < n; i += 2) {
74+
if (A[i] % 2 == 1) {
75+
while (A[j] % 2 == 1) {
76+
j += 2;
77+
}
78+
swap(A, i, j);
79+
}
80+
}
81+
return A;
82+
}
83+
84+
public void swap(int[] A, int i, int j) {
85+
int temp = A[i];
86+
A[i] = A[j];
87+
A[j] = temp;
88+
}
89+
}
90+
```
91+
92+
### 复杂度分析
93+
94+
- 时间复杂度:O(N),其中 N 是数组 A 的长度。
95+
96+
- 空间复杂度:O(1)。
97+

0 commit comments

Comments
 (0)