Skip to content

Commit cf373d6

Browse files
author
quchao161
committed
add daily exercise
1 parent 4c61917 commit cf373d6

File tree

7 files changed

+134
-134
lines changed

7 files changed

+134
-134
lines changed

Diff for: data_struct_study/.idea/workspace.xml

+45-99
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Diff for: data_struct_study/src/array_problem/Solution344.java

+30-10
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@
44
/**
55
* 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
66
*
7-
* 不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
7+
* 不要创建另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
88
*
99
* 你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
1010
*
11-
*  
12-
*
1311
* 示例 1:
1412
*
1513
* 输入:["h","e","l","l","o"]
@@ -23,15 +21,37 @@
2321
*/
2422
public class Solution344 {
2523

26-
public static String reverseRecursive(String s){
27-
int length = s.length();
28-
if(length<=1){
24+
// 1、递归解法会占用递归栈空间
25+
public String reverseString(String s) {
26+
// 1、初始化数组长度 & 当长度<=1说明不需要反转
27+
int len = s.length();
28+
if (len <=1 ) {
2929
return s;
30+
}
31+
32+
// 2、在递归的过程中不断反转当前字符串的左子字符串与右子字符串,注意右在前,左在后,就是为了实现反转的效果
33+
String leftStr = s.substring(0, len / 2);
34+
String rightStr = s.substring(len / 2, len);
35+
return reverseString(rightStr) + reverseString(leftStr);
36+
}
3037

38+
// 2、双指针解法,不断交换数组当前的首元素与尾元素,一个for循环搞定
39+
// 时间复杂度:O(n),空间复杂度:O(1)
40+
public void reverseString(char[] nums) {
41+
// 1、初始化数组长度
42+
int len = nums.length;
43+
44+
// 2、在for循环中不断交换当前的首元素与尾元素
45+
for (int l = 0, r = len - 1; l < r; ++l, --r) {
46+
char t = nums[l];
47+
nums[l] = nums[r];
48+
nums[r] = t;
3149
}
32-
String left = s.substring(0,length/2);
33-
String right = s.substring(length/2 ,length);
34-
String afterReverse = reverseRecursive(right)+reverseRecursive(left);//此处是递归的方法调用
35-
return afterReverse;
50+
}
51+
52+
public static void main(String[] args) {
53+
// ["h","e","l","l","o"]
54+
String s = "hello";
55+
System.out.println(new Solution344().reverseString(s));
3656
}
3757
}

Diff for: data_struct_study/src/array_problem/Solution_1.java

+29-11
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,44 @@
33
/**
44
* 数组中只出现一次的数字:一个整型数组里除了两个数字之外,
55
* 其他的数字都出现了两次,找出这两个数。
6-
*
7-
* 两个不相等的元素在位级表示上必定会有一位存在不同,将数组的所有
8-
* 元素异或得到的结果为不存在重复的两个元素异或的结果。
9-
*
10-
* diff &= -diff 得到出 diff 最右侧不为 0 的位,也就是不存在
11-
* 重复的两个元素在位级表示上最右侧不同的那一位,利用这一位就可以
12-
* 将两个元素区分开来。
136
*/
147
public class Solution_1 {
158

9+
10+
// 1、哈希法:遍历数组,用map记录所有元素出现的次数,然后再遍历数组,找出只出现一次的数。
11+
// 时间复杂度:O(n), 空间复杂度:O(n)
12+
// 2、位运算:两个不相等的元素在位级表示上必定会有一位存在不同,将数组的所有元素异或得到的结果
13+
// 为不存在重复的两个元素异或的结果。
14+
// diff &= -diff 得出 diff 最低位的1,也就是不存在重复的两个元素在位级表示上最右侧不同
15+
// 的那一位,利用这一位就可以将两个元素区分开来。
16+
// 时间复杂度:O(n), 空间复杂度:O(1)
1617
public void FindNumsAppearOnce(int[] nums, int num1[], int num2[]) {
18+
19+
// 1、利用 0 ^ x = x 和 x ^ y = 1、x ^ x = 0 的性质来遍历数组,
20+
// 最后得到的值就是两个不同元素异或的值
1721
int diff = 0;
18-
for (int num : nums)
22+
for(int num:nums) {
1923
diff ^= num;
24+
}
25+
26+
// 2、利用 x & -x 得到x最低位的1
2027
diff &= -diff;
21-
for (int num : nums) {
22-
if ((num & diff) == 0)
28+
29+
// 3、遍历数组:利用 最低位1 & 当前元素是否为0来分离两个不同的元素
30+
for(int num:nums) {
31+
// 注意这里加括号
32+
if ((diff & num) == 0) {
2333
num1[0] ^= num;
24-
else
34+
} else {
2535
num2[0] ^= num;
36+
}
2637
}
2738
}
39+
40+
public static void main(String[] args) {
41+
int[] nums = new int[]{1, 2, 3, 2, 1, 4};
42+
int[] num1 = new int[]{0};
43+
int[] num2 = new int[]{0};
44+
new Solution_1().FindNumsAppearOnce(nums, num1, num2);
45+
}
2846
}

Diff for: data_struct_study/src/array_problem/Solution_2.java

+30-14
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package array_problem;
22

33
/**
4-
* 多数投票问题,可以利用 Boyer-Moore Majority Vote Algorithm
5-
* 来解决这个问题,使得时间复杂度为 O(N)。
4+
* 多数投票问题,可以利用 Boyer-Moore 投票算法
5+
* 来解决这个问题,使得时间复杂度为 O(n)。
66
*
77
* 使用 cnt 来统计一个元素出现的次数,当遍历到的元素和统计元素相等时,
88
* 令 cnt++,否则令 cnt--。如果前面查找了 i 个元素,且 cnt == 0,
@@ -13,19 +13,35 @@
1313
*/
1414
public class Solution_2 {
1515

16-
public int MoreThanHalfNum_Solution(int[] nums) {
17-
int majority = nums[0];
18-
for (int i = 1, cnt = 1; i < nums.length; i++) {
19-
cnt = nums[i] == majority ? cnt + 1 : cnt - 1;
20-
if (cnt == 0) {
21-
majority = nums[i];
22-
cnt = 1;
16+
// 1、哈希表:用hashMap统计所有元素出现的次数,时间复杂度O(n), 空间复杂度O(n)
17+
// 2、排序:如果将数组 nums 中的所有元素按照单调递增或单调递减的顺序排序,
18+
// 那么下标为n/2的元素一定是众数。时间复杂度O(nlog(n)),空间复杂度O(logn)(自己实现堆排序O(1))
19+
// 3、Boyer Moore投票算法:时间复杂度O(n), 空间复杂度O(1)
20+
public int majorityElement(int[] nums) {
21+
22+
// 1、初始化出现次数和候选众数
23+
int count = 0;
24+
Integer candidate = null;
25+
26+
// 2、遍历数组
27+
for (int num : nums) {
28+
// 3、如果出现次数为0,则更新当前的候选众数
29+
if (count == 0) {
30+
candidate = num;
2331
}
32+
// 4、然后更新当前候选众数的出现次数:当前元素与候选众数相等,则+1,否则-1
33+
count += (num == candidate) ? 1 : -1;
2434
}
25-
int cnt = 0;
26-
for (int val : nums)
27-
if (val == majority)
28-
cnt++;
29-
return cnt > nums.length / 2 ? majority : 0;
35+
36+
// 5、最后的候选众数就是真正的众数
37+
// 为什么?如果候选众数不是真正的众数,则真正众数会和其它非候选人一起反对,此时候选众数就会下台(count==0),
38+
// 如果候选众数是真正的众数,则真正的众数就会支持,其它非获选人会一起反对,此时候选众数最后一定会当选。
39+
return candidate;
3040
}
41+
42+
public static void main(String[] args) {
43+
int[] nums = new int[]{2,2,1,1,1,2,2};
44+
System.out.println(new Solution_2().majorityElement(nums));
45+
}
46+
3147
}

0 commit comments

Comments
 (0)