【模拟面试】#19 复制带随机指针的链表 文件的最长绝对路径 分割等和子集

题目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 和一个空的二级子目录 subsubdir1subdir2 包含一个二级子目录 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

给定一个只包含正整数非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

注意:

  1. 每个数组中的元素不会超过 100
  2. 数组的大小不会超过 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];

    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值