算法刷题计划(三)扁平化多级双向链表、 Z 字形变换、两个字符串的删除操作、整数反转


(1)扁平化多级双向链表

  • 题目:
    ····多级双向链表中,除了指向下一个节点和前一个节点指针之外,它还有一个子链表指针,可能指向单独的双向链表。这些子列表也可能会有一个或多个自己的子项,依此类推,生成多级数据结构,如下面的示例所示。
    ····给你位于列表第一级的头节点,请你扁平化列表,使所有结点出现在单级双链表中。
  • 示例 1:

输入:head = [1,2,3,4,5,6,null,null,null,7,8,9,10,null,null,11,12]
输出:[1,2,3,7,8,11,12,9,10,4,5,6]
解释:

输入的多级列表如下图所示:

在这里插入图片描述

扁平化后的链表如下图:
在这里插入图片描述

  • 示例 2:

输入:head = [1,2,null,3]
输出:[1,3,2]
解释:

输入的多级列表如下图所示:

1—2---NULL
|
3—NULL

  • 示例 3:

输入:head = []
输出:[]


解题思路:
1)暴力解决方法:
首先新建一个链表栈,接着逐个链表段判断是否为空或是否有儿子,若两者都没有则最后返回该整段链表,若遇到有儿子的链段则将该链段的下一个链段放入链表栈中,等儿子那段链表判断结束后再拼接回来。

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* prev;
    Node* next;
    Node* child;
};
*/
class Solution
{
public:
    Node *flatten(Node *head)
    {
		stack<Node*>place;
		if(head==nullptr)	return nullptr;
		Node*current=head;
		while(current){
			if(current->child){
				if(current->next)	place.push(current->next);
				current->next=current->child;
			}
			current->child=nullptr;
			if(current->next==nullptr&& !place.empty()){
				current->next=place.top();
				place.pop();
			}
			if(current->next){
				current->next->prev=current;
			}
			current=current->next;
		}
		return head;
    }
};

2)递归解决方法:

class Solution {
    vector<Node*>v;
public:
    Node* flatten(Node* head) {
        dfs(head);
        int n =v.size();
        for(int i =0;i<n;i++){
            if(i>0) v[i]->prev=v[i-1];
            if(i+1<n)   v[i]->next=v[i+1];
            v[i]->child=NULL;  
        }
        return head;
    }
    void dfs(Node*head){
        if(head==NULL)return ;
        v.push_back(head);
        dfs(head->child);
        dfs(head->next);
    }
};

(2)Z 字形变换

  • 题目:

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:

P   A   H   N
A P L S I I G
Y   I   R

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);
  • 示例 1:
    输入:s = “PAYPALISHIRING”, numRows = 3
    输出:“PAHNAPLSIIGYIR”

  • 示例 2:
    输入:s = “PAYPALISHIRING”, numRows = 4
    输出:“PINALSIGYAHRPI”
    解释:

     P     I    N
     A   L S  I G
     Y A   H R
     P     I
    
  • 示例 3:
    输入:s = “A”, numRows = 1
    输出:“A”


解题思路:

class Solution {
public:
    string convert(string s, int numRows) {
        vector<string>str(numRows);
        string res;
        if(s.empty()||numRows<1)return res;
        if(numRows==1)return s;
        for(int i =0;i<s.size();i++){
            int ans=i/(numRows-1);
            int cur=i%(numRows-1);
            if(ans%2==0){
                str[cur].push_back(s[i]);
            }else{
                str[numRows-cur-1].push_back(s[i]);
            }
        }
        for(int i=0;i<str.size();i++){
            res+=str[i];
        }
        return res;
    }
};
class Solution {
public:
    string convert(string s, int numRows) {

        if (numRows == 1) return s;

        vector<string> rows(min(numRows, int(s.size())));
        int curRow = 0;
        bool goingDown = false;

        for (char c : s) {
            rows[curRow] += c;
            if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
            curRow += goingDown ? 1 : -1;
        }

        string ret;
        for (string row : rows) ret += row;
        return ret;
    }
};


(3)两个字符串的删除操作

  • 题目:
    给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符。

  • 示例:

    输入: “sea”, “eat”
    输出: 2
    解释: 第一步将"sea"变为"ea",第二步将"eat"变为"ea"


解题思路:(动态规划)

class Solution {
public:
    int minDistance(string word1, string word2) {
        vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1));
        for (int i = 0; i <= word1.size(); i++) dp[i][0] = i;
        for (int j = 0; j <= word2.size(); j++) dp[0][j] = j;
        for (int i = 1; i <= word1.size(); i++) {
            for (int j = 1; j <= word2.size(); j++) {
                if (word1[i - 1] == word2[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    dp[i][j] = min({dp[i - 1][j - 1] + 2, dp[i - 1][j] + 1, dp[i][j - 1] + 1});
                }
            }
        }
        return dp[word1.size()][word2.size()];
    }
};

(4)整数反转

  • 题目:

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。

  • 示例 1:

输入:x = 123
输出:321

  • 示例 2:

输入:x = -123
输出:-321

  • 示例 3:

输入:x = 120
输出:21

  • 示例 4:

输入:x = 0
输出:0


  • 解题思路:
    1)整数转字符串反转
class Solution{
    public:
        int reverse1(int x){
            if(x==0||x>INT_MAX||x<INT_MIN)  return 0;

            string str=to_string(x);
            reverse(str.begin(),str.end());
            long num = atoll(str.c_str());
            return (x<0)?(-num):num;
        }
    }

2)整数取余

class Solution {
public:
    int reverse(int x) {
        long n=0;
        while(x){
            n=n*10+x%10;
            x/=10;
        }
        return n>INT_MAX||n<INT_MIN?0:n;
    }
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值