题目1
给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的 深拷贝。
我们用一个由 n
个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index]
表示:
val
:一个表示Node.val
的整数。random_index
:随机指针指向的节点索引(范围从0
到n-1
);如果不指向任何节点,则为null
。
示例 1:
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]] 输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
示例 2:
输入:head = [[1,1],[2,1]] 输出:[[1,1],[2,1]]
示例 3:
输入:head = [[3,null],[3,0],[3,null]] 输出:[[3,null],[3,0],[3,null]]
示例 4:
输入:head = [] 输出:[] 解释:给定的链表为空(空指针),因此返回 null。
提示:
-10000 <= Node.val <= 10000
Node.random
为空(null)或指向链表中的节点。- 节点数目不超过 1000 。
思路及代码
剑指Offer原题,三次遍历,重点关注第一次的创建完节点后,插入原来的链表 以及 最后一次断开链表分别获得两个链表
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
if(head == NULL){return NULL;}
//一,先给所有的节点进行一次拷贝
Node* cur = head;
Node* newNode = NULL;
while(cur)
{
newNode = new Node(cur->val);
newNode->next = cur->next;
cur->next = newNode;
cur = newNode->next;
}
//二,将所有拷贝的节点进行赋值
cur = head;
while(cur)
{
newNode = cur->next;
if(cur->random)
newNode->random = cur->random->next;
cur = newNode->next;
}
//三,拆开新链表和原链表
Node* newhead = head->next;
cur = head;
while(cur->next)
{
newNode = cur->next;
cur->next = newNode->next;
cur = newNode;
}
return newhead;
}
};
题目2
假设我们以下述方式将我们的文件系统抽象成一个字符串:
字符串 "dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext"
表示:
dir subdir1 subdir2 file.ext
目录 dir
包含一个空的子目录 subdir1
和一个包含一个文件 file.ext
的子目录 subdir2
。
字符串 "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext"
表示:
dir subdir1 file1.ext subsubdir1 subdir2 subsubdir2 file2.ext
目录 dir
包含两个子目录 subdir1
和 subdir2
。 subdir1
包含一个文件 file1.ext
和一个空的二级子目录 subsubdir1
。subdir2
包含一个二级子目录 subsubdir2
,其中包含一个文件 file2.ext
。
我们致力于寻找我们文件系统中文件的最长 (按字符的数量统计) 绝对路径。例如,在上述的第二个例子中,最长路径为 "dir/subdir2/subsubdir2/file2.ext"
,其长度为 32
(不包含双引号)。
给定一个以上述格式表示文件系统的字符串,返回文件系统中文件的最长绝对路径的长度。 如果系统中没有文件,返回 0
。
说明:
- 文件名至少存在一个
.
和一个扩展名。 - 目录或者子目录的名字不能包含
.
。
要求时间复杂度为 O(n)
,其中 n
是输入字符串的大小。
请注意,如果存在路径 aaaaaaaaaaaaaaaaaaaaa/sth.png
的话,那么 a/aa/aaa/file1.txt
就不是一个最长的路径。
思路及代码
来源:https://blog.csdn.net/qq_32805671/article/details/89523848
class Solution {
public:
int lengthLongestPath(string input) {
int res = 0, n = input.size(), level = 0;
map<int, int> m {{0, 0}};
for (int i = 0; i < n; ++i) {
int start = i;
while (i < n && input[i] != '\n' && input[i] != '\t')
++i;
if (i >= n || input[i] == '\n') {
string t = input.substr(start, i - start);
if (t.find('.') != string::npos) //string:npos是个特殊值,说明查找没有匹配
res = max(res, m[level] + (int)t.size());
else {
++ level;
m[level] = m[level - 1] + (int)t.size() + 1;
}
level = 0;
}
else
++ level;
}
return res;
}
};
题目3
给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
注意:
- 每个数组中的元素不会超过 100
- 数组的大小不会超过 200
示例 1:
输入: [1, 5, 11, 5] 输出: true 解释: 数组可以分割成 [1, 5, 5] 和 [11].
示例 2:
输入: [1, 2, 3, 5] 输出: false 解释: 数组不能分割成两个元素和相等的子集.
思路及代码
背包问题求解。
来源:https://blog.csdn.net/Xiao2018428/article/details/106130064
class Solution {
public:
bool canPartition(vector<int>& nums) {
int len = nums.size();
if (len == 0) return false;
int sum = 0;
for (int n : nums)
sum += n;
if (sum % 2 == 1) return false;
vector<vector<bool>>dp(len + 1, vector<bool>(sum / 2 + 1,false));
for (int i = 0; i <= len; i++)
dp[i][0] = true;
for (int i = 1; i < len + 1; i++)
{
for (int j = 1; j <= sum / 2; j++)
{
if (j - nums[i - 1] < 0)
// 背包容量不足,不能装入第 i 个物品
dp[i][j] = dp[i - 1][j];
else
dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i - 1]];
}
}
return dp[len][sum/2];
}
};