26.Remove Duplicates from Sorted Array
Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
Example 1:
Given nums = [1,1,2], Your function should return length =2
, with the first two elements ofnums
being1
and2
respectively. It doesn't matter what you leave beyond the returned length.
solution:
从排序号的数组中移走重复的数字。做一个快指针和慢指针。
如果快指针和慢指针相等,那么快指针就向前移动,如果不相等,当快指针没有到结尾时循环,那么让慢指针的下一个数字等于快指针的数字。并且让快指针向下移动一步。
代码实现如下:
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if (nums.empty()) return 0;
int pre = 0, cur = 0, n = nums.size();
while (cur < n) {
if (nums[pre] == nums[cur]) ++cur;
else nums[++pre] = nums[cur++];
}
return pre + 1;
}
};
27.Remove Element
从数组中移走指定的数字
Given an array nums and a value val, remove all instances of that value in-place and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
The order of elements can be changed. It doesn't matter what you leave beyond the new length.
Example 1:
Given nums = [3,2,2,3], val = 3,
Your function should return length = 2, with the first two elements of nums being 2.
It doesn't matter what you leave beyond the returned length.
solution: 和上一题一样 做一个快指针和个慢指针,当快指针没有到结尾时循环,如果快指针等于val(指定移走的数字)
那么快指针向前移动, 如果不等 那么慢指针等于快指针所指数字。 并且让快指针和慢指针一起向前移动。
注意:这两道题都可以用快慢指针来做,但是需要注意慢指针在是++在前 还是++在后,可以用一个简单的小数组来过一下流程。
28.Implement strStr()
找一个字符串中的固定的子串的起始位置。
Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
Example 1:
Input: haystack = "hello", needle = "ll"
Output: 2
Example 2:
Input: haystack = "aaaaa", needle = "bba"
Output: -1
solution:可以有两个方法来实现,首先是暴力算法,对字符串的每个字符进行字串匹配。 时间复杂度为O(M*N)
还有一种方法是KMP算法。这里略去,之前学过,长时间不看我自己都忘了。
KMP代码实现算法如下
class Solution {
public:
vector<int> getNext (string s){
int n = s.size();
vector<int> next(n);
next[0] = 0;
if (n == 1)
return next;
next[1] = 0;
int k = 0;
for (int i = 2; i < n; i++){
while (k > 0 && s[i-1] != s[k])
k = next[k];
if (s[i-1] == s[k])
k += 1;
next[i] = k;
}
return next;
}
int strStr(string s1, string s2){
int i = 0;
int j = 0;
int len1 = s1.size();
int len2 = s2.size();
if (len2 == 0)
return 0;
vector<int> next = getNext(s2);
while (i < len1 && j < len2){
if (len1 - i < len2 - j)
break;
if (s1[i] == s2[j]){
++i;
++j;
}
else{
if (j == 0)
++i;
else
j = next[j];
}
}
if (j == len2)
return i - len2;
else
return -1;
29.Divide Two Integers
Given two integers dividend
and divisor
, divide two integers without using multiplication, division and mod operator.
Return the quotient after dividing dividend
by divisor
.
The integer division should truncate toward zero.
Example 1:
Input: dividend = 10, divisor = 3 Output: 3
Example 2:
Input: dividend = 7, divisor = -3 Output: -2
Note:
- Both dividend and divisor will be 32-bit signed integers.
- The divisor will never be 0.
- Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. For the purpose of this problem, assume that your function returns 231 − 1 when the division result overflows.
不用 乘除,取余符号计算除法。
solution: 首先想到了小学老师时长教导我们的,除法的本质就是看被除数包含了多少个除数。
所以我打算用加法,直到除数大于被除数时,看一下计数值即可。但是这里很明显时间过长。如果是INT_MAX 除以2
要循环次数。。。
所以我们这里采用位运算符,首先把特殊的可能越界的情况都处理掉。然后用long long 类型保存中间结果,防止数值越界,
令N=除数
接下来每次对N进行循环,如果被除数大于N的的两倍
那么N向左移位,计数值也移位。循环结束时,从被除数中减去这个N。继续下一次循环,N又从=除数开始。
最后返回计数值。
代码实现如下:
int divide(int dividend, int divisor) {
if (divisor == 0 || (dividend == INT_MIN && divisor == -1)) return INT_MAX;
long long m=abs((long long)dividend);
long long n=abs((long long )divisor);
int sign;
long long res=0;
if((dividend<0)^(divisor<0)) sign=-1;
else sign=1;
if (n == 1) return sign == 1 ? m : -m;
while(n<=m)
{
long long t=n,p=1;
while(m>(t<<1))
{
t<<=1;
p<<=1;
}
m-=t;
res+=p;
}
return (sign==1)?res:-res;
}
30.Substring with Concatenation of All Words
You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.
Example 1:
Input:
s = "barfoothefoobarman",
words = ["foo","bar"]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are "barfoor" and "foobar" respectively.
The output order does not matter, returning [9,0] is fine too.
Example 2:
Input:
s = "wordgoodgoodgoodbestword",
words = ["word","good","best","word"]
Output: []
找字符串中包含小字符串合集的起始位置。
solution:首先给小字符串建立一个哈希表,然后开始对大字符串进行循环,由于小字符串的长度固定,那么长字符串每次的步长也是确定的。小字符串的长度为n,共M个,那么循环到字符串size()-n*m为之
这时建立第二个哈希表,把每一个遇到的字符放进去,如果第一个哈希表中不存在,那么break内层循环
如果重复,也break 直到第二个哈希表的size和第一个一样为之。
代码实现如下:
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
vector<int> res;
if (s.empty() || words.empty()) return res;
int n = words.size(), m = words[0].size();
unordered_map<string, int> m1;
for (auto &a : words) ++m1[a];
for (int i = 0; i <= (int)s.size() - n * m; ++i) {
unordered_map<string, int> m2;
int j = 0;
for (j = 0; j < n; ++j) {
string t = s.substr(i + j * m, m);
if (m1.find(t) == m1.end()) break;
++m2[t];
if (m2[t] > m1[t]) break;
}
if (j == n) res.push_back(i);
}
return res;
}
};