852. 山脉数组的峰顶索引;162. 寻找峰值;165. 比较版本号;166. 分数到小数;171. Excel表列序号;172. 阶乘后的零

这篇博客探讨了如何在山脉数组中找到峰顶索引,以及解决寻找峰值元素、比较版本号、分数到小数转换和计算阶乘后零数的问题。提供的示例展示了不同算法的实现和应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们把符合下列属性的数组 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;
    }
};

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值