我们把符合下列属性的数组 A 称作山脉:
A.length >= 3
存在 0 < i < A.length - 1 使得A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1]
给定一个确定为山脉的数组,返回任何满足 A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1] 的 i 的值。
示例 1:
输入:[0,1,0]
输出:1
示例 2:
输入:[0,2,1,0]
输出:1
提示:
3 <= A.length <= 10000
0 <= A[i] <= 10^6
A 是如上定义的山脉
class Solution {
public:
int peakIndexInMountainArray(vector<int>& A) {
int le = 1, ri = A.size() - 2;
while (le <= ri) {
int mid = le + ((ri - le) >> 1);
if (A[mid] > A[mid - 1] && A[mid] > A[mid + 1]) return mid;
else if (A[mid] <= A[mid - 1]) ri = mid - 1;
else le = mid + 1;
}
return -1;
}
};
峰值元素是指其值大于左右相邻值的元素。
给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。
数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞。
示例 1:
输入: nums = [1,2,3,1]
输出: 2
解释: 3 是峰值元素,你的函数应该返回其索引 2。
示例 2:
输入: nums = [1,2,1,3,5,6,4]
输出: 1 或 5
解释: 你的函数可以返回索引 1,其峰值元素为 2;
或者返回索引 5, 其峰值元素为 6。
说明:
你的解法应该是 O(logN) 时间复杂度的。
class Solution {
public:
int findPeakElement(vector<int>& nums) {
if (nums.size() == 1) return 0; // 除此情况外,不可能有mid_le,mid_ri同时越界的情况存在
int le = 0, ri = nums.size() - 1, pos = -1;
while (le <= ri) {
int mid = le + ((ri - le) >> 1);
int mid_le = mid - 1, mid_ri = mid + 1;
if (mid_le != -1 && mid_ri != nums.size()) { // 正常情况:顶端/增/减/底端
if (nums[mid] > nums[mid_le] && nums[mid] > nums[mid_ri]) {
return mid;
} else if (nums[mid] < nums[mid_ri]) {
le = mid_ri;
} else {
ri = mid_le;
}
} else if (mid_le == -1) { // mid_le -> mid: 必增情况
if (nums[mid] > nums[mid_ri]) return mid;
else le = mid_ri;
} else { // mid -> mid_ri: 必减情况
if (nums[mid] > nums[mid_le]) return mid;
else ri = mid_le;
}
}
return -1;
}
};
比较两个版本号 version1 和 version2。
如果 version1 > version2 返回 1,如果 version1 < version2 返回 -1, 除此之外返回 0。
你可以假设版本字符串非空,并且只包含数字和 . 字符。
. 字符不代表小数点,而是用于分隔数字序列。
例如,2.5 不是“两个半”,也不是“差一半到三”,而是第二版中的第五个小版本。
你可以假设版本号的每一级的默认修订版号为 0。例如,版本号 3.4 的第一级(大版本)和第二级(小版本)修订号分别为 3 和 4。其第三级和第四级修订号均为 0。
示例 1:
输入: version1 = "0.1", version2 = "1.1"
输出: -1
示例 2:
输入: version1 = "1.0.1", version2 = "1"
输出: 1
示例 3:
输入: version1 = "7.5.2.4", version2 = "7.5.3"
输出: -1
示例 4:
输入:version1 = "1.01", version2 = "1.001"
输出:0
解释:忽略前导零,“01” 和 “001” 表示相同的数字 “1”。
示例 5:
输入:version1 = "1.0", version2 = "1.0.0"
输出:0
解释:version1 没有第三级修订号,这意味着它的第三级修订号默认为 “0”。
提示:
版本字符串由以点 (.) 分隔的数字字符串组成。这个数字字符串可能有前导零。
版本字符串不以点开始或结束,并且其中不会有两个连续的点。
class Solution {
public:
int compareVersion(string version1, string version2) {
stringstream ss1(version1), ss2(version2);
string s1, s2;
while (true) {
auto &b1 = getline(ss1, s1, '.'); // 必须引用
auto &b2 = getline(ss2, s2, '.'); // 不能是bool, 因为istream& getline (istream& is, string& str, char delim);
if (!b1 && !b2) {
return 0;
} else if (!b1) {
if (stoi(s2)) return -1;
} else if (!b2) {
if (stoi(s1)) return 1;
} else {
auto int_s1 = stoi(s1), int_s2 = stoi(s2);
if (int_s1 == int_s2) continue;
else if (int_s1 > int_s2) return 1;
else return -1;
}
}
}
};
给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以字符串形式返回小数。
如果小数部分为循环小数,则将循环的部分括在括号内。
示例 1:
输入: numerator = 1, denominator = 2
输出: "0.5"
示例 2:
输入: numerator = 2, denominator = 1
输出: "2"
示例 3:
输入: numerator = 2, denominator = 3
输出: "0.(6)"
class Solution {
public:
string fractionToDecimal(int numerator, int denominator) { // 小数部分如果余数重复出现两次就表示该小数是循环小数了
if (denominator == 0) return "";
if (numerator == 0) return "0";
string result;
long long num = static_cast<long long>(numerator); // 转换为longlong防止溢出
long long denom = static_cast<long long>(denominator);
if ((num>0) ^ (denom>0))result.push_back('-'); // 处理正负号,一正一负取负号
num = llabs(num); denom = llabs(denom);
result.append(to_string(num / denom)); // 处理整数部分
// 处理小数部分
num %= denom;
if (num == 0)return result;
result.push_back('.');
int index = result.size() - 1;
unordered_map<int, int> record; // map用来记录出现重复数的下标,然后将'('插入到重复数前面就好了
while (num&&record.count(num) == 0) { // 小数部分:余数不为0且余数还没有出现重复数字
record[num] = ++index;
num *= 10; // 余数扩大10倍,然后求商,和草稿本上运算方法是一样的
result += to_string(num / denom);
num %= denom;
}
if (record.count(num) == 1) { // 出现循环余数,我们直接在重复数字前面添加'(',字符串末尾添加')'
result.insert(record[num], "(");
result.push_back(')');
}
return result;
}
};
给定一个Excel表格中的列名称,返回其相应的列序号。
例如,
A -> 1
B -> 2
C -> 3
...
Z -> 26
AA -> 27
AB -> 28
...
示例 1:
输入: "A"
输出: 1
示例 2:
输入: "AB"
输出: 28
示例 3:
输入: "ZY"
输出: 701
class Solution {
public:
int titleToNumber(string s) {
int res = 0;
for (auto &i: s) {
res = 26*res + static_cast<int>(i - 'A' + 1);
}
return res;
}
};
给定一个整数 n,返回 n! 结果尾数中零的数量。
示例 1:
输入: 3
输出: 0
解释: 3! = 6, 尾数中没有零。
示例 2:
输入: 5
输出: 1
解释: 5! = 120, 尾数中有 1 个零.
说明: 你算法的时间复杂度应为 O(log n) 。
class Solution {
public:
int trailingZeroes(int n) {
int res = 0;
while (n >= 5) {
res += n / 5;
n /= 5;
}
return res; // return n/5+n/25+n/125+n/625+n/3125+n/15625+n/78125+n/390625+n/1953125+n/9765625+n/48828125+n/244140625+n/1220703125;
}
};