Ex1: 求和:
给定一个具有n个整数的数组,问在S中是否存在3个元素a、b、c使得a + b + c = 0。
注意:三元组(a、b、c)必须是一个非递减顺序(即a<=b<=c)。输出的结果不能重复
例如,给定数组S = [-1 0 1 2 -1 -4],输出[-1, 0, 1]以及[-1, -1, 2]
oj地址:https://leetcode.com/problems/3sum/description/
代码1
先上一个针对Matrix的AC代码(输入输出没有LeetCode严格)
#include<iostream>
#include <set>
#include <algorithm>
using namespace std;
int num[1000050];
set<pair<int, pair<int, int>>> ans;
int main() {
int n;
pair<int,pair<int, int>> temp;
cin >> n;
for (int i = 0; i < n; i++)
cin >> num[i];
sort(num, num + n);
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
for (int k = j+1; k < n; k++) {
temp = make_pair(num[i], make_pair(num[j], num[k]));
if (num[i] + num[j] + num[k] == 0 && ans.find(temp) == ans.end()) {
ans.insert(temp);
printf("%d %d %d\n", num[i], num[j], num[k]);
}
}
return 0;
}
思路:纯暴力,没啥思路
note: 对set、find()、insert等使用仍然不熟练,甚至概念不清
代码2
LeetCode AC代码
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
int n=nums.size(),left,right;
sort(nums.begin(),nums.end()); //注意参数
for(int i=0;i<n-2;i++){
if(i>0 && nums[i]==nums[i-1]) continue;
left=i+1,right=n-1;
while(left<right){
int sum=nums[i]+nums[right]+nums[left];
if(sum>0) right--;
else if(sum<0) left++;
else{
ans.push_back(vector<int>{nums[i],nums[left],nums[right]});
while(left+1<right && nums[left+1]==nums[left]) left++;
while(right-1>left && nums[right-1]==nums[right]) right--;
left++,right--;
}
}
}
return ans;
}
};
思路:
首先将数组由小到大排序,使用sort函数,这里我本来写的是sort(num,num+n)在VS上是通过了,可是leetcode上出现了编译错误,还没有研究是什么原因。
i先指向第一个元素,left指向i后一个元素,right指向数组最后一个元素,
然后求得他们的和sum,如果sum比0小,说明元素需要更大一点,所以就让left右移;
反之,如果sum比0大,说明元素需要更小一点,所以就让right左移。
如果sum为0,就将数组nums[i],nums[left],nums[right]}加入ans中,同时将left右移,right左移。
只不过为了避免重复,在左右指针移动的时候要判断下一个指向的元素是不是和之前相同,指针i同理。
Ex2:最短前缀
一个字符串的前缀是从该字符串的第一个字符起始的一个子串。例如“carbon”的前缀是有“c”,“ca”,“car”,“carb”,“carbo”,和“carbon”。空串不是前缀,但是每个非空串是它自身的子串。我们希望能用前缀来缩略地表示单词。例如“carbohydrate”通常用“carb”来表示。在下面的例子中,“carbohydrate”能被缩写成“carboh”,但是不能被缩写成“carbo”(或其余更短的前缀),因为已经有一个单词用“carbo”开始。
carbohydrate
cart
carbonic
caribou
carriage
car
一个完全匹配会覆盖一个前缀匹配,例如“car”完全匹配单词“car”。因此“car”是“car”的缩略语是没有二义性的,“car”不会被当成“carriage”或者任何在列表中以“car”开始的单词。
现在给你一组单词,要求找到所有单词唯一标识的最短前缀。
输入描述:
输入包含多组数据,每组数据第一行包含一个正整数n(2≤n≤1000)。
紧接着n行单词,单词只有小写字母组成,长度不超过20个字符。
输出描述:
对应每一组数据,按照输入顺序依次输出每个单词的最短前缀。
每组数据之后输出一个空格作为分隔。
示例输入:
3
ab
a
acb
6
carbohydrate
cart
carbonic
caribou
carriage
car
示例输出:
ab
a
ac
carboh
cart
carbon
cari
carr
car
oj地址:http://poj.org/problem?id=2001 (稍有不同)
代码1
针对Matrix可以过
#include <string>
#include <iostream>
using namespace std;
string word[1050];
int main(){
int n;
bool valid;
string sub;
while (cin >> n) {
for (int i = 0; i < n; i++) cin >> word[i];
for (int i = 0; i < n; i++) {
for (int j = 1; j <= word[i].length(); j++) {
sub = word[i].substr(0, j);
valid = true;
for (int k = 0; k < n; k++) {
if (k != i&&word[k].find(sub) == 0 && j < word[i].length()) {
valid = false;
break;
}
}
if (valid) {
cout << sub << endl;
break;
}
}
}
cout << endl;
}
return 0;
}
纯暴力,三重循环。
对于每个word,先取前1个字符,看在其余的字符中是否有重复前缀;
若有重复前缀,且当前的sub并非完全匹配,则sub向后扩展一位;
否则就是它的最短前缀。