目录
133、克隆图
题目
给你无向 连通 图中一个节点的引用,请你返回该图的 深拷贝(克隆)。
图中的每个节点都包含它的值 val(int) 和其邻居的列表(list[Node])。
class Node {
public int val;
public List<Node> neighbors;
}
测试用例格式:
简单起见,每个节点的值都和它的索引相同。例如,第一个节点值为 1(val = 1),第二个节点值为 2(val = 2),以此类推。该图在测试用例中使用邻接列表表示。
邻接列表 是用于表示有限图的无序列表的集合。每个列表都描述了图中节点的邻居集。
给定节点将始终是图中的第一个节点(值为 1)。你必须将 给定节点的拷贝 作为对克隆图的引用返回。
示例 1:
输入:adjList = [[2,4],[1,3],[2,4],[1,3]]
输出:[[2,4],[1,3],[2,4],[1,3]]
解释:
图中有 4 个节点。
节点 1 的值是 1,它有两个邻居:节点 2 和 4 。
节点 2 的值是 2,它有两个邻居:节点 1 和 3 。
节点 3 的值是 3,它有两个邻居:节点 2 和 4 。
节点 4 的值是 4,它有两个邻居:节点 1 和 3 。
示例 2:输入:adjList = [[]]
输出:[[]]
解释:输入包含一个空列表。该图仅仅只有一个值为 1 的节点,它没有任何邻居。
示例 3:输入:adjList = []
输出:[]
解释:这个图是空的,它不含任何节点。
示例 4:输入:adjList = [[2],[1]]
输出:[[2],[1]]
提示:
节点数不超过 100 。
每个节点值 Node.val 都是唯一的,1 <= Node.val <= 100。
无向图是一个简单图,这意味着图中没有重复的边,也没有自环。
由于图是无向的,如果节点 p 是节点 q 的邻居,那么节点 q 也必须是节点 p 的邻居。
图是连通图,你可以从给定节点访问到所有节点。
通过次数47,496提交次数73,278
在真实的面试中遇到过这道题?是
否
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/clone-graph
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
方法一:深度优先搜索
方法二:广度优先搜索
代码
/*
// Definition for a Node.
class Node {
public:
int val;
vector<Node*> neighbors;
Node() {
val = 0;
neighbors = vector<Node*>();
}
Node(int _val) {
val = _val;
neighbors = vector<Node*>();
}
Node(int _val, vector<Node*> _neighbors) {
val = _val;
neighbors = _neighbors;
}
};
*/
class Solution {
public:
// 深度优先搜索
// Node* cloneGraph(Node* node)
// {
// if(node == nullptr) {
// return nullptr;
// }
// if(m.find(node) != m.end()) {
// return m[node];
// }
// Node *newNode = new Node(node->val);
// m[node] = newNode;
// for(int i = 0; i <(node->neighbors).size(); ++i) {
// Node *neighbor_node = cloneGraph(node->neighbors[i]);;
// m[node]->neighbors.push_back(neighbor_node);
// }
// return m[node];
// }
// private:
// unordered_map<Node*, Node*> m;
// 广度优先搜索
Node* cloneGraph(Node* node)
{
if(node == nullptr) {
return nullptr;
}
Node *newNode = new Node(node->val);
unordered_map<Node*, Node*> m;
m[node] = newNode;
queue<Node*> que;
que.push(node);
while(!que.empty()) {
Node* n = que.front();
que.pop();
for(Node *neighbor: n->neighbors) {
if(m.find(neighbor) == m.end()) {
que.push(neighbor);
m[neighbor] = new Node(neighbor->val);
}
m[n]->neighbors.emplace_back(m[neighbor]);
}
}
return m[node];
}
// //广度优先遍历
// /*
// Node* cloneGraph(Node* node)
// {
// //若传入的node为空指针,则返回空
// if(node == nullptr) {
// return nullptr;
// }
// Node *newNode = new Node(node->val);
// unordered_map<Node*, Node*> m;
// m[node] = newNode;
// queue<Node*> que;
// que.push(node);
// //当队列不为空时
// while(!que.empty()) {
// Node *n = que.front();
// que.pop();
// for(Node *neighbor: n->neighbors) {
// if(m.find(neighbor) == m.end()) {
// que.push(neighbor);
// m[neighbor] = new Node(neighbor->val);
// }
// m[n]->neighbors.emplace_back(m[neighbor]);
// }
// }
// return m[node];
// }
// */
// //深度优先遍历
// private:
// unordered_map<Node*, Node*> m;
// public:
// Node* cloneGraph(Node* node)
// {
// if(node == nullptr) {
// return nullptr;
// }
// if(m.find(node) != m.end()) {
// return m[node];
// }
// Node *newNode = new Node(node->val);
// m[node] = newNode;
// for(Node *neighbor: node->neighbors) {
// m[node]->neighbors.emplace_back(cloneGraph(neighbor));
// }
// return m[node];
// }
};
134、加油站
题目
在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。
你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。
如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。
说明:
如果题目有解,该答案即为唯一答案。
输入数组均为非空数组,且长度相同。
输入数组中的元素均为非负数。
示例 1:输入:
gas = [1,2,3,4,5]
cost = [3,4,5,1,2]输出: 3
解释:
从 3 号加油站(索引为 3 处)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油
开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油
开往 0 号加油站,此时油箱有 8 - 2 + 1 = 7 升汽油
开往 1 号加油站,此时油箱有 7 - 3 + 2 = 6 升汽油
开往 2 号加油站,此时油箱有 6 - 4 + 3 = 5 升汽油
开往 3 号加油站,你需要消耗 5 升汽油,正好足够你返回到 3 号加油站。
因此,3 可为起始索引。
示例 2:输入:
gas = [2,3,4]
cost = [3,4,3]输出: -1
解释:
你不能从 0 号或 1 号加油站出发,因为没有足够的汽油可以让你行驶到下一个加油站。
我们从 2 号加油站出发,可以获得 4 升汽油。 此时油箱有 = 0 + 4 = 4 升汽油
开往 0 号加油站,此时油箱有 4 - 3 + 2 = 3 升汽油
开往 1 号加油站,此时油箱有 3 - 3 + 3 = 3 升汽油
你无法返回 2 号加油站,因为返程需要消耗 4 升汽油,但是你的油箱只有 3 升汽油。
因此,无论怎样,你都不可能绕环路行驶一周。来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/gas-station
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
方法一:暴力法
方法二:一次遍历
代码
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
// 方法一:暴力法
// int n = gas.size();
// for(int i = 0; i < n * 2; i++) {
// int count = 0;
// int j = i;
// int sum = 0;
// while(j < n * 2 && (sum = sum + gas[j % n]) >= cost[j % n]) {
// sum -= cost[j % n];
// j++;
// count++;
// if(count == n + 1) {
// return i;
// }
// }
// }
// return -1;
int total = 0, current = 0;
int start_position = 0;
for(int i = 0; i < gas.size(); ++i) {
total += gas[i] - cost[i];
current += gas[i] - cost[i];
if(current < 0) {
start_position = i + 1;
current = 0;
}
}
return total >= 0 ? start_position : -1;
}
};
135、分发糖果
题目
老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。
你需要按照以下要求,帮助老师给这些孩子分发糖果:
每个孩子至少分配到 1 个糖果。
相邻的孩子中,评分高的孩子必须获得更多的糖果。
那么这样下来,老师至少需要准备多少颗糖果呢?示例 1:
输入: [1,0,2]
输出: 5
解释: 你可以分别给这三个孩子分发 2、1、2 颗糖果。
示例 2:输入: [1,2,2]
输出: 4
解释: 你可以分别给这三个孩子分发 1、2、1 颗糖果。
第三个孩子只得到 1 颗糖果,这已满足上述两个条件。来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/candy
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
两次扫描
代码
class Solution {
public:
int candy(vector<int>& ratings) {
int n = ratings.size();
vector<int> left_candy(n, 1);
vector<int> right_candy(n, 1);
for(int i = 1; i < n; i++) {
if(ratings[i] > ratings[i - 1]) {
left_candy[i] = left_candy[i - 1] + 1;
}
}
for(int j = n - 2; j >= 0; j--) {
if(ratings[j] > ratings[j + 1]) {
right_candy[j] = right_candy[j + 1] + 1;
}
}
int sum = 0;
for(int k = 0; k < n; k++) {
sum += max(left_candy[k], right_candy[k]);
}
return sum;
}
};
136、只出现一次的数字
题目
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:输入: [4,1,2,1,2]
输出: 4来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/single-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
异或
代码
class Solution {
public:
int singleNumber(vector<int>& nums) {
// 交换律:a ^ b ^ c <=> a ^ c ^ b
// 任何数与0异或为任何数 0 ^ n => n
// 相同的数异或为0: n ^ n => 0
int result = 0;
for(int num: nums) {
result = result ^ num;
}
return result;
}
};
137、只出现一次的数字II
题目
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,3,2]
输出: 3
示例 2:输入: [0,1,0,1,0,1,99]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/single-number-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
异或
非
代码
class Solution {
public:
int singleNumber(vector<int>& nums) {
/*
0 ^ x = x,
x ^ x = 0;
x & ~x = 0,
x & ~0 =x
*/
int a = 0;
int b = 0;
for(int num: nums) {
b = (b ^ num) & (~a);
a = (a ^ num) &(~b);
}
return b;
}
};