面试经典150题0426
Leetcode068 文本左右对齐
贪心:每一行尽量放更多的单词。对于最后一行要特殊处理。对于一行只有一个单词的,将单词左对齐。对于其他普通情况,需要计算空格能否平均分配到间隙中,如果不能,向下取整,然后将多余的空格从左到右分配到每个间隙中。
public static List<String> fullJustify(String[] words, int maxWidth){
List<String> ans = new ArrayList<>();
int n = words.length;
List<String> list = new ArrayList<>();
for (int i = 0; i < n;) {
// 移除列表中的所有元素
list.clear();
list.add(words[i]);
// 记录当前单词的长度
int currLen = words[i++].length();
// 填充maxWidth的最大单词数量
// +1为每个单词后最少跟随一个空格
while (i < n && currLen + 1 + words[i].length() <= maxWidth){
// 没满,继续尝试填充
currLen += 1 + words[i].length();
list.add(words[i++]);
}
// 最后一行处理为左对齐
if(i == n){
StringBuilder sb = new StringBuilder(list.get(0));
for (int j = 1; j < list.size(); j++) {
sb.append(" ").append(list.get(j));
}
// 不满,将空格填充到最后
while (sb.length() < maxWidth){
sb.append(" ");
}
ans.add(sb.toString());
break;
}
int cnt = list.size();
// 当前行只有一个单词,特殊处理为左对齐
if(cnt == 1){
StringBuilder sb = new StringBuilder(list.get(0));
while (sb.length() != maxWidth){
sb.append(" ");
}
ans.add(sb.toString());
continue;
}
// 其余情况
// 当前行单词总长度 = 总长度 - 空格数量
int wordWidth = currLen - (cnt - 1);
// 需要填充的空格数量
int spaceWidth = maxWidth - wordWidth;
// 单词中间需要填充的空格数量,需要向下取整
int spaceItemWidth = spaceWidth / (cnt - 1);
StringBuilder spaceItem = new StringBuilder();
for (int j = 0; j < spaceItemWidth; j++) {
spaceItem.append(" ");
}
StringBuilder sb = new StringBuilder();
for(int k = 0, sum = 0; k < cnt; k++){
sb.append(list.get(k));
if(k == cnt - 1){
break;
}
sb.append(spaceItem);
sum += spaceItemWidth;
// 剩余单词间的间隙数量
// cnt - k - 1为处理到第k个单词剩余间隙数量,再减1代表当前单词后面的间隙已经处理
int remain = cnt - k - 1 - 1;
if(remain * spaceItemWidth + sum < spaceWidth){
// 将不能平均分配到所有间隙的空格数量,尽量安排到靠左的间隙中
sb.append(" ");
sum++;
}
}
ans.add(sb.toString());
}
return ans;
}
Leetcode125 验证回文串
双指针:先将字符串中大写字母转为小写字母,然后左指针和右指针分别扫描字符,扫描到字母或者数字则进行判断,否则继续移动指针。
public static boolean isPalindrome(String s){
int left = 0, right = s.length() - 1;
String str = s.toLowerCase();
while (left < right){
while (left < right && !Character.isLetter(str.charAt(left)) && !Character.isDigit(str.charAt(left))){
left++;
}
while (left < right && !Character.isLetter(str.charAt(right)) && !Character.isDigit(str.charAt(right))){
right--;
}
if(str.charAt(left) != str.charAt(right)){
return false;
}
left++;
right--;
}
return true;
}
s.toLowerCase()
:将字符串中大写字母转换为小写字母。
Character.isLetter()
:判断字符是否为字母。
Character.isDigit()
:判断字符是否为数字。
Leetcode392 判断子序列
双指针:两个指针分别指向字符串
s
和字符串t
,字符相等两个指针同时移动,不相等只移动s
的指针。
public static boolean isSubsequence(String s, String t){
int sPtr = 0, tPtr = 0;
while (sPtr < s.length() && tPtr < t.length()){
if(s.charAt(sPtr) == t.charAt(tPtr)) {
sPtr++;
tPtr++;
continue;
}
tPtr++;
}
return sPtr == s.length();
}
Leetcode167 两数之和Ⅱ 输入有序数组
双指针,分别指向数组两端。当指针所指两数之和小于
target
,左指针向右移动;大于target
时右指针向左移动。
public static int[] twoSum(int[] numbers, int target){
int left = 0, right = numbers.length - 1;
while (left < right){
int tmp = numbers[left] + numbers[right];
if(tmp == target){
return new int[]{left+1, right+1};
}
else if(tmp < target){
left++;
}
else {
right--;
}
}
return new int[]{-1, -1};
}