首页 > 其他分享 >Leetcode 11-15题

Leetcode 11-15题

时间:2024-02-17 20:16:36浏览次数:30  
标签:11 15 nums int vector mp ans Leetcode size

盛最多雨水的容器

数组的第\(i\)个数字表示这个位置隔板的高度,选择哪两块板子可以装最多的水,返回可以存储的最大水量。

有一种双指针的贪心策略:如果左边的指针所在的挡板低,就将左边的指针右移,否则将右边的指针左移。

每次移动完之后,计算当前能存储的水量,并和结果值相比较。

证明:假设最优解对应的两条线的下标是 \(i^′,j^′(i^′<j^′)\),在 \(i,j\) 不断靠近的过程中,不妨假设 \(i\) 先走到 \(i^′\),则此时有 \(j^′<j\)。反证,如果此时 \(a_i≤a_j\),设 \(S\) 表示 \(i,j\) 能盛多少水,\(S^′\) 表示 \(i^′,j^′\) 能盛多少水,则:

\[S=min(a_i,a_j)∗(j−i) =a_i∗(j−i) >a_i∗(j^′−i) \geq min(ai,aj^′)∗(j^′−i)=S^′ \]

与 \(S^′\) 是最优解矛盾,因此 \(a_i>a_j\),所以 \(j\) 会一直走到 \(j^′\),从而得到最优解。

int maxArea(vector<int>& height) {
    int res = 0;
    for(int l = 0, r = height.size() - 1; l < r; ) {
        res = max(res, (r - l) * min(height[l], height[r]));	// 先计算当前状态再转移
        if(height[l] < height[r])   l ++;
        else r --;
    }
    return res;
}

整数转罗马数字

在罗马数字中有如下规则:

I	1
V	5
X	10
L	50
C	100
D	500
M	1000

通常,罗马数字中小的数字在大的数字的右边,如XV表示\(15\)。但也存在特例,如IV表示\(4\),但这只有如下六种情况:

  • I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
  • X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
  • C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

将给定的数字转化为罗马数字。

1	  	2		3	 	4		5	   	6		 7		   	 8		    9
I	 	II	    III		IV		V	  	VI		 VII		 VIII		IX
10	 	20		30		40		50	  	60		 70			 80		    90
x	 	XX		XXX		XL		L	  	LX		 LXX		 LXXX		XC
100 	200 	300 	400 	500   	600 	 700 		 800 		900
c		CC		CCC		CD		D	  	DC		 DCC		 DCCC		CM
1000	2000	3000
M		MM		MMM

分别枚举个十百千位的数值如何表示,我们不难发现\(1-3\),\(6-8\)的表示比较显然,其余的则比较特殊。

以\(100-900\)为例,以\(100,400,500,900\)为界,若\(x>900\)则\(x-900\),若\(x>500\)则\(x-500\),直至循环结束。

所以只需要打表打出\(1,4,5,9\)系列的值即可,然后从大到小依次减。

string intToRoman(int num) {
    vector<int> key = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
    vector<string> value = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
    string ans = "";
    // 2649 -> 1649 -> 649 -> 149 -> 49	   		-> 9 		-> 0
    // 		   M	   MM     MMD    MMDC     MMDCXL 	MMDCXLIX
    for(int i = 0; i < key.size(); i ++) {
        while(num >= key[i]) {
            num -= key[i];
            ans += value[i];
        }
    }
    return ans;
}

罗马数字转整数

将给定的罗马数字转化为整数。

和上一题类似的打表思想,但是将罗马数字转化为整数时,注意到一个特性:

若大数在小数左边,则为大数+小数,若大数在小数右边,则为大数-小数。并且本题只需要存储7个罗马数字即可。

int romanToInt(string s) {
    unordered_map<char, int> mp;
    mp['I'] = 1;    mp['V'] = 5;    mp['X'] = 10;   mp['L'] = 50;
    mp['C'] = 100;  mp['D'] = 500;  mp['M'] = 1000;

    int ans = 0;
    for(int i = 0; i < s.size(); i ++) {
        if(i + 1 < s.size() && mp[s[i]] < mp[s[i + 1]])
            ans -= mp[s[i]];
        else
            ans += mp[s[i]];
    }
    return ans;
}

最长公共前缀

求字符串数组中的最长公共前缀。

可以用trie树来做,但是太麻烦。

可以直接枚举字符串的每一位,看所有字符串的这一位是否都相同,如果不同就返回当前结果,否则继续下一轮判断。

string longestCommonPrefix(vector<string>& strs) {
    string ans = "";
    for(int i = 0; i < strs[0].size(); i ++) {  // 枚举第i位
        char c = strs[0][i];
        bool flag = true;
        for(auto str : strs) {                  // 判断所有字符串的第i位是否都相同
            if(str.size() < i || str[i] != c) {
                flag = false;
                break;
            }
        }
        if(flag)    ans += c;
        else    break;
    }
    return ans;
}

三数之和

给定整数数组,找出满足\(i \neq j \neq k\)且nums[i]+nums[j]+nums[k]=0的所有三元组。

先对整数数组排序,然后枚举\(i\)的所有位置,再对\(j,k\)使用双指针算法。

当\(i\)的位置固定后,\(nums[j]+nums[k]=-nums[i]\),当\(j\)右移时,\(k\)必然左移,因此时间复杂度为\(O(n^2)\)。

由于答案中不能包含重复的三元组,可以使用set来对答案进行去重。

vector<vector<int>> threeSum(vector<int>& nums) {
    set<vector<int>> res;
    sort(nums.begin(), nums.end());
    for(int i = 0; i < nums.size() - 2; i ++) {     // 固定i
        for(int j = i + 1, k = nums.size() - 1; j < k; j ++) {  // 每次移动j,对j找到满足条件的k
            while(j < k - 1 && nums[i] + nums[j] + nums[k] > 0) k --;
            if(nums[i] + nums[j] + nums[k] == 0)
                res.insert({nums[i], nums[j], nums[k]});
        }
    }
    vector<vector<int>> ans;            // 去重
    for(auto p : res)   ans.push_back(p);
    return ans;
}

对于1 1 2 2 -3这种情况来说,第1个1和第2个1所呈现出的组合是一样的,所以对于相同的数ij都只需要遍历一次即可。

也可以通过这种方法来去重,会大大降低时间复杂度。

vector<vector<int>> threeSum(vector<int>& nums) {
    vector<vector<int>> ans;
    sort(nums.begin(), nums.end());
    for(int i = 0; i < nums.size() - 2; i ++) {     // 固定i
        if(i && nums[i] == nums[i - 1]) continue;   // i不能重复判断 
        for(int j = i + 1, k = nums.size() - 1; j < k; j ++) {  // 每次移动j,对j找到满足条件的k
            if(j > i + 1 && nums[j] == nums[j - 1])  continue;  // j不能重复判断
            // 因为i和j都不会重复,所以k也必然不会重复,所以不需要额外特判k
            while(j < k - 1 && nums[i] + nums[j] + nums[k] > 0) k --;
            if(nums[i] + nums[j] + nums[k] == 0)
                ans.push_back({nums[i], nums[j], nums[k]});
        }
    }
    return ans;
}

标签:11,15,nums,int,vector,mp,ans,Leetcode,size
From: https://www.cnblogs.com/xushengxiang/p/18018273

相关文章

  • P1136 迎接仪式
    本题只有必要对j和z进行最多m次交换,也就是重新编排序列,通过记录跟原序列有何差别来保证m次交换。可以维护\(f[i][k_1][k_2][0/1]\)表示在第1到i位中把\(k_1\)个'j'换成了'z',\(k_2\)个'z'换成了'j',最后一位是'j'还是'z'(为了转移时计数)。这时总共进行了\(k_1+k_2\)次操作,第1~i位中......
  • P5155 [USACO18DEC] Balance Beam P
    假设有一个长度为\(L\)的木块。定义\(f_i\)从\(i\)走到\(L\)的概率,有\(f_i=\dfrac{f_{i+1}+f_{i-1}}{2}\)。由\(f_1=0,f_L=1\)可以递推得出\(f_i=\dfrac{i}{L}\)。若一个节点移动的期望收益比当前点停止的收益低,则设这个点为关键点。从\(i\)出发开始移动,期望收益......
  • CF1540E Tasty Dishes
    Description初始有\(n\)个数\(a_i\),以及若干条有向边\((u_i,v_i)\),保证\(u_i<v_i\)。一轮操作会形如下面两个过程:首先\(\foralli,a_i:=\max(a_i,ia_i)\)。然后\(\foralli,a'_i:=a_i+\sum\limits_{(i,j)\inE}\max(a_j,0)\),最后\(\foralli,a_i:=a'_i\)。......
  • Windows 11 24H2升级更苛刻:一些旧电脑上从“不受支持”变为“无法启动”
    Windows1124H2对一些旧电脑的支持更加苛刻了。微软官方已经确认,Windows的下一个大版本将命名为Windows1124H2(预计会在9月发布),并非早先外界猜测的Windows12。据多家国外媒体报道,Windows1124H2在某些旧电脑上将从“不受支持”变为“无法启动”。大家都知道,Windows11发布......
  • Windows 11 24H2速度起飞:首次正式支持USB4 80 Gbps!
    USB4v2.0标准官宣两年,终于迎来了Windows11的正式支持。据悉,刚刚确认的Windows1124H2,将是首个支持USB4v2.0标准(即80Gbps速率)的Windows正式版本。此举早有迹象。在此之前,微软已经率先向Windows11Dev预览版用户发布了Windows11Build23615预览版更新,本次更新主要是增加了......
  • P1595 信封问题
    题目描述某人写了nn封信和nn个信封,如果所有的信都装错了信封。求所有信都装错信封共有多少种不同情况。输入格式一个信封数nn,保证n≤20n≤20。输出格式一个整数,代表有多少种情况。输入输出样例输入#12输出#11输入#23输出#22说明/提示对于100%100%的数......
  • P1135 奇怪的电梯
    题目背景感谢@yummy提供的一些数据。题目描述呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第ii层楼(1≤i≤N1≤i≤N)上有一个数字KiKi​(0≤Ki≤N0≤Ki​≤N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不......
  • 代码随想录算法训练营第十七天 | 110.平衡二叉树 (优先掌握递归)| 404.左叶子之和 (优先
    257.二叉树的所有路径 已解答简单 相关标签相关企业 给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。叶子节点 是指没有子节点的节点。示例1:输入:root=[1,2,3,null,5]输出:["1->2->5","1->3"]示例2:输入:ro......
  • 代码随想录算法训练营第十六天 | 104.二叉树的最大深度| 559.n叉树的最大深度|222.完
    222.完全二叉树的节点个数 已解答简单 相关标签相关企业 给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中......
  • 2月11日总结
    个提问:你的编程能力从什么时候开始突飞猛进的?↓↓↓今天,我们就这个话题一起来做个讨论。我的回答话说这个话题着实有点泛、难以回答,这里简单跟大家分享一下我对于这个问题的一些看法,希望大家喜欢。我的观点认为,一个程序员但凡编程能力突飞猛进之后,会在如下6个能力方面有所体......