2019.1.5 leetcode 刷题总结
题号:905
给定一个非负整数数组 A,返回一个由 A 的所有偶数元素组成的数组,后面跟 A 的所有奇数元素。
你可以返回满足此条件的任何数组作为答案。
示例:
输入:[3,1,2,4]
输出:[2,4,3,1]
输出 [4,2,3,1],[2,4,1,3] 和 [4,2,1,3] 也会被接受。
我的想法:
双指针法:一个指向奇数的指针,一个指向偶数的指针,遍历数组,不断移动偶数指针,直到它指向偶数,将偶数和奇数数值调换,奇数指针向前移动,不断重复,直到偶数指针指向最后一个元素
对应程序:
// java
class Solution {
public int[] sortArrayByParity(int[] A) {
// 指向奇数的指针
int j = 0;
// 指向偶数的指针
int k = 0;
while(k < A.length) {
// 当偶数指针指向偶数
if(A[k] % 2 == 0) {
// 交换两个指针指向的数值
int temp = A[k];
A[k] = A[j];
A[j] = temp;
// 指向奇数的指针向前移动
j++;
}
// 不断移动指向偶数的指针
k++;
}
return A;
}
}
题号:804
国际摩尔斯密码定义一种标准编码方式,将每个字母对应于一个由一系列点和短线组成的字符串, 比如: “a” 对应 “.-”, “b” 对应 “-…”, “c” 对应 “-.-.”, 等等。
为了方便,所有26个英文字母对应摩尔斯密码表如下:
[".-","-…","-.-.","-…",".","…-.","–.","…","…",".—","-.-",".-…","–","-.","—",".–.","–.-",".-.","…","-","…-","…-",".–","-…-","-.–","–…"]
给定一个单词列表,每个单词可以写成每个字母对应摩尔斯密码的组合。例如,“cab” 可以写成 “-.-…–…”,(即 “-.-.” + “-…” + ".-"字符串的结合)。我们将这样一个连接过程称作单词翻译。
返回我们可以获得所有词不同单词翻译的数量。
例如:
输入: words = [“gin”, “zen”, “gig”, “msg”]
输出: 2
解释:
各单词翻译如下:
“gin” -> “–…-.”
“zen” -> “–…-.”
“gig” -> “–…--.”
“msg” -> “–…--.”
共有 2 种不同翻译, “–…-.” 和 “–…--.”.
我的想法:
- 定义字典:小写字母和摩尔斯密码的关系映射
- 遍历数组,针对每个单词,将其转换为摩尔斯密码所表示的字符串,存入Set中
- 返回Set集合的大小
对用程序:
// java
class Solution {
// 用数组下标和字符串作映射,不需要map
private static final String[] DICTIONARY = {
".-","-...","-.-.","-..",".","..-.","--.","....","..",
".---","-.-",".-..","--","-.","---",".--.","--.-",
".-.","...","-","..-","...-",".--","-..-","-.--","--.."};
public int uniqueMorseRepresentations(String[] words) {
Set<String> res = new HashSet<>();
for(String word : words) {
StringBuilder sb = new StringBuilder();
for(char c : word.toCharArray()) {
// 利用小写字母的ASCII码值
// 减掉97,变成数组下标
sb.append(DICTIONARY[c - 97]);
}
res.add(sb.toString());
}
return res.size();
}
}
题号:657
在二维平面上,有一个机器人从原点 (0, 0) 开始。给出它的移动顺序,判断这个机器人在完成移动后是否在 (0, 0) 处结束。
移动顺序由字符串表示。字符 move[i] 表示其第 i 次移动。机器人的有效动作有 R(右),L(左),U(上)和 D(下)。如果机器人在完成所有动作后返回原点,则返回 true。否则,返回 false。
注意:机器人“面朝”的方向无关紧要。 “R” 将始终使机器人向右移动一次,“L” 将始终向左移动等。此外,假设每次移动机器人的移动幅度相同。
示例 1:
输入: “UD”
输出: true
解释:机器人向上移动一次,然后向下移动一次。所有动作都具有相同的幅度,因此它最终回到它开始的原点。因此,我们返回 true。
示例 2:
输入: “LL”
输出: false
解释:机器人向左移动两次。它最终位于原点的左侧,距原点有两次 “移动” 的距离。我们返回 false,因为它在移动结束时没有返回原点。
我的想法:
- 把向上移动(U)和向下移动(D)看做一组,把向左移动(L)和向右移动(R)看作一组
- 用两个栈分别记录两组行动,当栈为空时或栈中有此行动时,当前行动入栈;否则移除栈顶元素
- 最后看两个栈的元素是否都为零,若是,返回true;否则返回false
对应程序:
// java
class Solution {
public boolean judgeCircle(String moves) {
if(moves.length() % 2 != 0) {
return false;
}
LinkedList<Character> udStack = new LinkedList<>();
LinkedList<Character> lrStack = new LinkedList<>();
for(char move : moves.toCharArray()) {
switch(move) {
case 'U':
case 'D':
howToDo(udStack, move);
break;
case 'L':
case 'R':
howToDo(lrStack, move);
break;
}
}
if(udStack.size() != 0 || lrStack.size() != 0) {
return false;
}
return true;
}
private void howToDo(LinkedList<Character> stack, char c) {
if(stack.size() == 0 || stack.contains(c)) {
stack.addFirst(c);
}else {
stack.removeFirst();
}
}
}
优化:
以上方法显然有些麻烦,其实,分别记录四种方向的移动次数,比较对应行动方向(U-D,L-R)的移动次数是否相同即可
程序:
// java
class Solution {
public boolean judgeCircle(String moves) {
// 参数检查,步数为奇数一定不能回到原点
if(moves.length() % 2 != 0) {
return false;
}
int u = 0,
d = 0,
l = 0,
r = 0;
for(char move : moves.toCharArray()) {
switch(move) {
case 'U':
u++;
break;
case 'D':
d++;
break;
case 'L':
l++;
break;
case 'R':
r++;
break;
}
}
return u == d && l == r;
}
}
题号:922
给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。
对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。
你可以返回任何满足上述条件的数组作为答案。
示例:
输入:[4,2,5,7]
输出:[4,5,2,7]
解释:[4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。
我的想法:
双指针法:一个指向数组中的数字,另一个指向该数字的前一个数字。判断当前数字是否符合规则,若符合,指针向前移动;若不符合,移动第二个指针,移动的大小为2,同样找到不符合规则的数字,交换,重复
对应程序:
// java
class Solution {
public int[] sortArrayByParityII(int[] A) {
// 遍历整个数组的指针
int j = 0;
// 和指针j错开一位的指针
int k = 1;
while(j < A.length) {
// 若当前位置上的数字不符合规则
// (奇数 + 偶数 = 偶数 + 奇数 = 奇数)
if((A[j] + j) % 2 != 0) {
// 找到对应不符合规则的数
// (若当前是奇数下标值为偶数,那么就去找偶数下标值为奇数的数)
if((A[k] + k) % 2 != 0) {
// 交换两个数
int temp = A[k];
A[k] = A[j];
A[j] = temp;
// 指针后移
j++;
k = j + 1;
}else {
// 去下一个位置找
k += 2;
}
}else {
// 指针后移
j++;
k = j + 1;
}
}
return A;
}
}
优化:
其实没有必要检查每一个数字和下标是否符合规则,只检查奇数下标或偶数下标的数即可,因为数组中奇偶数字各一半,若偶数位置出现了不符合规则的数字,那么奇数位置上一定也存在不符合规则的数字
程序:
// java
class Solution {
public int[] sortArrayByParityII(int[] A) {
// 指向奇数下标的指针
int j = 1;
// 只遍历偶数下标的数字
for(int i = 0; i < A.length - 1; i += 2) {
// 若不符合条件
if(A[i] % 2 != 0) {
// 去奇数下标的数字中寻找不符合规则的数字
while(A[j] % 2 != 0) {
j += 2;
}
// 交换数字
int temp = A[j];
A[j] = A[i];
A[i] = temp;
}
}
return A;
}
}
以上两种方法都是在原数组的基础上对数组进行修改并返回的,也就是没有使用额外的存储空间,当然这道题也可以定义一个新的数组,遍历原数组,将奇数填充到新数组的奇数索引中,把偶数填充到偶数索引中,再将新数组返回即可,这里就不提供代码了,大家可以自己写一写。