每一步向前都是向自己的梦想更近一步,坚持不懈,勇往直前!
第一题:26. 删除有序数组中的重复项 - 力扣(LeetCode)
class Solution {
public int removeDuplicates(int[] nums) {
if(nums.length == 1){
return 1;
}
int slow = 0;
for(int fast = 1; fast < nums.length; fast++){
//快慢指针
if(nums[fast] != nums[fast - 1]){
slow++;
nums[slow] = nums[fast];
}
}
return slow + 1;
}
}
class Solution {
public int removeElement(int[] nums, int val) {
int l = 0;
for(int r = 0; r < nums.length; r++){
//这比上一题还简单... 快慢指针
if(nums[r] != val){
nums[l] = nums[r];
l++;
}
}
return l;
}
}
第三题:28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)
class Solution {
public int strStr(String haystack, String needle) {
if (haystack == null || needle == null || needle.length() == 0) {
return -1;
}
int[] lps = computeLPSArray(needle);
int i = 0, j = 0;
while (i < haystack.length()) {
if (needle.charAt(j) == haystack.charAt(i)) {
i++;
j++;
}
if (j == needle.length()) {
return i - j;
}
if (i < haystack.length() && needle.charAt(j) != haystack.charAt(i)) {
if (j != 0) {
j = lps[j - 1];
} else {
i = i + 1;
}
}
}
return -1;
}
private int[] computeLPSArray(String pattern) {
//KMP算法
int length = pattern.length();
int[] lps = new int[length];
int i = 1, j = 0;
lps[0] = 0; // lps[0] 总是0
while (i < length) {
if (pattern.charAt(i) == pattern.charAt(j)) {
lps[i] = j + 1;
i++;
j++;
} else {
if (j != 0) {
j = lps[j - 1];
} else {
lps[i] = 0;
i++;
}
}
}
return lps;
}
}
class Solution {
static final int MAX = Integer.MAX_VALUE;
static final int MIN = Integer.MIN_VALUE;
public int divide(int dividend, int divisor) {
// 溢出情况
if (dividend == MIN && divisor == -1) {
return MAX;
}
// 记录结果的符号
int sign = -1;
if ((dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0)) {
sign = 1;
}
// 全部转换成负数,防止溢出
dividend = dividend > 0 ? -dividend : dividend;
divisor = divisor > 0 ? -divisor : divisor;
int ans = 0;
// 倍乘法,注意都是负数了,比较的时候与正数相反
// 简单点理解,就是每次减去除数的 2^x 倍数,剩下的部分继续按这样的规则继续
while (dividend <= divisor) {
int tmp = divisor, count = 1;
// 这里注意不要写成 tmp + tmp >= dividend,这样写加法有可能会溢出导致死循环
while (tmp >= dividend - tmp) {
// tmp 和 count 每次增加一倍,所以叫倍增
tmp += tmp;
count += count;
}
// 被除数减去除数的 2^x 倍数做为新的被除数
dividend -= tmp;
// count 即 2^x
ans += count;
}
return sign < 0 ? -ans : ans;
}
}
第五题:30. 串联所有单词的子串 - 力扣(LeetCode)
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> res = new ArrayList<Integer>();
int m = words.length, n = words[0].length(), ls = s.length();
// 遍历可能的起始位置
for (int i = 0; i < n; i++) {
// 如果剩余字符串长度小于总单词长度,跳出循环
if (i + m * n > ls) {
break;
}
// 用于存储单词出现次数的映射
Map<String, Integer> differ = new HashMap<String, Integer>();
// 计算子串中每个单词的出现次数
for (int j = 0; j < m; j++) {
String word = s.substring(i + j * n, i + (j + 1) * n);
differ.put(word, differ.getOrDefault(word, 0) + 1);
}
// 减少words数组中每个单词的计数
for (String word : words) {
differ.put(word, differ.getOrDefault(word, 0) - 1);
if (differ.get(word) == 0) {
differ.remove(word);
}
}
// 滑动窗口检查子串
for (int start = i; start < ls - m * n + 1; start += n) {
// 移动窗口时调整映射
if (start != i) {
String word = s.substring(start + (m - 1) * n, start + m * n);
differ.put(word, differ.getOrDefault(word, 0) + 1);
if (differ.get(word) == 0) {
differ.remove(word);
}
word = s.substring(start - n, start);
differ.put(word, differ.getOrDefault(word, 0) - 1);
if (differ.get(word) == 0) {
differ.remove(word);
}
}
// 如果映射为空,表示子串中包含了所有单词
if (differ.isEmpty()) {
res.add(start);
}
}
}
return res;
}
}