剑指 Offer 58 - II. 左旋转字符串
转转转
1 | class Solution { |
1 | class Solution { |
参考34. Find First and Last Position of Element in Sorted Array
1 | class Solution { |
O(n)
1 | class Solution { |
优化 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30class Solution {
public:
int search(vector<int>& nums, int target) {
if(nums.empty())
return 0;
int lo = 0, hi = nums.size() - 1;
while(lo < hi)
{
int mid = (lo + hi) >> 1;
if(nums[mid] < target)
lo = mid + 1;
else
hi = mid;
}
int left = hi; // 最后保留一个等于目标的左边界
if(nums[lo] != target)
return 0;
hi = nums.size() - 1;
while(lo < hi)
{
int mid = ((lo + hi) >> 1) + 1; // 偏向右边
if(nums[mid] <= target)
lo = mid;
else
hi = mid - 1;
}
// 保留一个等于左边的左边界
return lo - left + 1;
}
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31class Solution {
public:
int search(vector<int>& nums, int target) {
if(nums.empty())
return 0;
int lo = 0, hi = nums.size() - 1;
while(lo <= hi)
{
int mid = (lo + hi) >> 1;
if(nums[mid] < target)
lo = mid + 1;
else
hi = mid - 1;
}
// 当他们相等时候,进入会出现hi在lo的前面一位,即hi是左边界而lo是左边界右边一个,hi!=target而lo==target
int left = hi;
if(lo <= nums.size() - 1 && nums[lo] != target) // lo如果不等于的话,那就直接跳出
return 0;
hi = nums.size() - 1;
while(lo <= hi)
{
int mid = (lo + hi) >> 1;
if(nums[mid] <= target)
lo = mid + 1;
else
hi = mid - 1;
}
// lo是右边界
return lo - left - 1;
}
};
1 | class Solution { |
T(n) : O(n)
S(n) : O(n)
1 | class Solution { |
最简单的dp
1 | class Solution { |
1 | class Solution { |
version.1 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Solution {
public:
int translateNum(int num) {
string str = to_string(num);
vector<int> dp(str.size());
dp[0] = 1;
for(int i = 1; i < str.size(); ++i)
{
dp[i] += dp[i - 1];
auto num = (str[i - 1] - '0') * 10 + str[i] - '0';
if(num >= 10 && num < 26)
dp[i] += (i >= 2 ? dp[i - 2] : 1);
}
return dp.back();
}
};
优化dp的空间,但字符串还是占O(n) 1
2
3
4
5
6
7
8
9
10
11
12
13
14class Solution {
public:
int translateNum(int num) {
string str = to_string(num);
int a = 1, b = 1;
for(int i = 1; i < str.size(); ++i)
{
auto num = (str[i - 1] - '0') * 10 + str[i] - '0';
a = (num >= 10 && num < 26) ? a + b : b;
swap(a, b);
}
return b;
}
};
直接使用取余计算数位 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18class Solution {
public:
int translateNum(int num) {
int a = 1, b = 1;
int lastNum = num % 10;
num /= 10;
while(num)
{
auto curNum = num % 10;
auto sum = curNum * 10 + lastNum;
a = (sum >= 10 && sum < 26) ? a + b : b;
num /= 10;
lastNum = curNum;
swap(a, b);
}
return b;
}
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Solution {
public:
int translateNum(int num) {
if(num < 10)
return 1;
int ret = 0;
int a = num % 10;
num /= 10;
int b = num % 10;
if(b != 0 && b * 10 + a < 26)
ret += translateNum(num / 10);
ret += translateNum(num);
return ret;
}
};
类似179. 最大数
本质上转换为一个排序问题,对于两个数字a1,b1。当str(a1) + str(b1) < str(b1) + str(a1)
时,表示a1因当刚在b1左边,反之则表示a1应当放在b1右边。以此为判断条件对数组进行排序,排序后重新组合成字符串就是所需
1 | class Solution { |
v2 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37class Solution {
public:
string minNumber(vector<int>& nums) {
string ret = "";
vector<string> strs;
for(auto& num : nums)
strs.push_back(to_string(num));
sort(strs, 0, nums.size() - 1);
for(auto& str : strs)
ret += str;
return ret;
}
private:
int partition(vector<string>& nums, int lo, int hi)
{
int i = lo, j = hi + 1;
string c = nums[lo];
while(i < j)
{
while(i < hi && nums[++i] + c < c + nums[i]) {}
while(j > lo && nums[--j] + c > c + nums[j]) {}
if(i >= j)
break;
swap(nums[i], nums[j]);
}
swap(nums[j], nums[lo]);
return j;
}
void sort(vector<string>& nums, int lo, int hi)
{
if(lo > hi)
return;
auto j = partition(nums, lo, hi);
sort(nums, lo, j - 1);
sort(nums, j + 1, hi);
}
};1
2
3
4
5
6
7
8
9
10
11
12
13class Solution {
public:
string minNumber(vector<int>& nums) {
vector<string> strs;
for(auto& num : nums)
strs.push_back(to_string(num));
sort(strs.begin(), strs.end(), [](string& str1, string str2){ return str1 + str2 < str2 + str1; });
string ret = "";
for(auto& str : strs)
ret.append(str);
return ret;
}
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19class Solution {
public:
string minNumber(vector<int>& nums) {
sort(nums.begin(), nums.end(), [](int a, int b)
{
long sa = 10;
long sb = 10;
while(sa <= a)
sa *= 10;
while(sb <= b)
sb *= 10;
return sb * a + b < sa * b + a;
});
string ret;
for(auto& num : nums)
ret += to_string(num);
return ret;
}
};
1 | class Solution { |
T(n) : O(n^2)
1 | class Solution { |
T(n) : O(n)
1 | class Solution { |
T(n) : O(n)
S(n) : O(n)
1 | class Solution { |
T(n) : O(n)
S(n) : O(1)
1 | 提醒一下,判断条件最好不要用相加后的结果,应该用target - nums[i] 跟 nums[j]比较,这样保证不会溢出。虽然这题中不会出错。同样的例子还有二分查找,(left + right) / 2 可以用left + ((rigth - left) >> 1))代替 |
1 | class Solution { |
T(n) : O(n)
S(n) : O(n)
因为其他数都出现三次,只有一个数出现一次,所以将所有数的每一位加起来后对3取余剩下的就是那个只出现一次的数字
对于每一位构建状态转换图,有三个状态0,1,2 其中三个状态为0,1,2表示除以3后的余数
求出来后的结果必然是00或01两个状态,因为所有出现三次的数都加完了取余完了,所以只剩下了这2种情况表示那个只出现一次的数的位为0或1,所以最后只需要返回one即可
对于每一位都是相同的方法,所以可以直接放到一起来用位运算
1 | class Solution { |
1 | class Solution { |
T(n) : O(n)
S(n) : O(1)