[LeetCode刷题] - LC006 ZigZag Conversion

Posted Ben土豆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[LeetCode刷题] - LC006 ZigZag Conversion相关的知识,希望对你有一定的参考价值。

题目描述

给定一个字符串,想让你用纵向zig-zag形式展开,然后在横向进行拼接输出最后的新字符串

LeetCode 006Can you solve this real interview question? - Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.https://leetcode.com/problems/zigzag-conversion/description/

题目思路

1. 纵向矩阵遍历

题目主要难点就是在于如何将字符串进行zig-zag展开,根据题目给的例子我们可以看出,当展开的列col是numRow-1的整数倍时,直接从从上到下依次将字符填充进去即可;对于其余中间列col,要以斜线的方式展开,这里的规律就是只在 行数row 满足 的时候,将字符填入,其余位置以空格补全。

代码如下:

    public String convert(String s, int numRows) 

        if (s==null || s.length()==0 || numRows<=1) return s;

 
        String[] strList = new String[numRows];
        for (int i=0; i<strList.length; i++) 
            strList[i]="";
        

        int col = 0;
        int cnt = 0;
        int l = s.length();

        int x = 0;
        while(cnt<l) 
            if (col%(numRows-1)==0) 
                strList[x] = strList[x] + s.charAt(cnt++);
             else 
                strList[x] = x==(numRows-1-col%(numRows-1))? strList[x]+s.charAt(cnt++) : strList[x]+" ";
            

            // if touch buttom move to next col
            if (++x >= numRows) 
                col++;
                x = 0;
            
        

        return printOut(strList);
    

    private String printOut(String[] strList) 
        String str = "";
        for(int i=0; i<strList.length; i++) 
            for(int j=0; j<strList[i].length(); j++) 
                if (strList[i].charAt(j)==' ') continue;

                str = str + strList[i].charAt(j);
            
        
        return str;
    

时间复杂度:;空间复杂度:。 

2.  位置关系推导

上述思路需要将字符串实际展开,会占用大量的时间和空间,如果我们能推导出每一行每一个元素对应的索引那么就可以省略逐列遍历的过程,直接拼接出字符串。

对于第一行和最后一行比较简单,两列直接没有多余字符,

对于中间行,除了上述相隔 列存在字符外,中间列也会存在一个字符,而该字符索引 

代码如下:

public String convert(String s, int numRows) 

        if (s==null || s.length()==0 || numRows<=1) return s;
        int l = s.length();
        // use StringBuilder() to append String is much faster than String + 
        StringBuilder str = new StringBuilder();
        
        for (int i=0; i<numRows; i++) 
            int st = i;
            int next1 = (numRows-1)*2;
            int next2 = (numRows-1)*2 - i*2;
            while(st<l) 
                if (i==0 || i==numRows-1) 
                    str.append(s.charAt(st));
                    st += next1;
                 else 
                    str.append(s.charAt(st));
                    if (st+next2<l) str.append(s.charAt(st+next2));
                    st += next1;
                
            
        

        return str.toString();
    

 时间复杂度:;空间复杂度:​​​​​​​。

算法刷题:LC初级算法

删除链表中的节点

请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点。传入函数的唯一参数为 要被删除的节点 。

示例 1:

输入:head = [4,5,1,9], node = 5
输出:[4,1,9]
解释:给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.

示例 2:

输入:head = [4,5,1,9], node = 1
输出:[4,5,9]
解释:给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.

提示:

链表至少包含两个节点。
链表中所有节点的值都是唯一的。
给定的节点为非末尾节点并且一定是链表中的一个有效节点。
不要从你的函数中返回任何结果。

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/top-interview-questions-easy/xnarn7/
来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

其实一开始我也没看太懂这个函数签名是什么意思,然后慢慢就懂了。

void deleteNode(ListNode* node) {
        node->val = node->next->val;
        node->next = node->next->next;
    }

删除链表的倒数第N个节点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

进阶:你能尝试使用一趟扫描实现吗?

思路:快慢指针。
先用快指针前进n,再用两个指针同时前进,这时候快指针到尾就是慢指针倒数第n的距离了。

ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode * fast = head;
        ListNode * slow = head;
        for(;n>0;n--)
            fast = fast->next;
        
        if(fast == NULL)
            return head->next;
        while(fast->next != NULL && slow->next->next != NULL){
            slow = slow->next;
            fast = fast->next;
        }

        slow->next = slow->next->next;

        return head;
    }

反转链表

思路:尾插法,这个真的又给我搞晕了。。。

ListNode* reverseList(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* curr = head;
        while (curr) {
            ListNode* next = curr->next;
            curr->next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }

回文链表

请判断一个链表是否为回文链表。

从中间解开,后面半部分翻转。
然后开始一一匹配呗。

bool func(ListNode* node, int n, int depth) {
        if (n % 2 && depth == n / 2) {
            return true;
        }
        if (n % 2 == 0 && depth == n / 2 - 1) {
            int temp = node -> next -> val;
            node -> next = node -> next -> next;
            return temp == node -> val;
        }
        int future = func(node->next, n, depth + 1);
        node -> next = node -> next -> next;
        int ret = node -> val == node -> next -> val;
        node -> next = node -> next -> next;
        return ret && future;
    }
    bool isPalindrome(ListNode* head) {
        int n = 0;
        auto p = head;
        while (p) {
            n ++;
            p = p -> next;
        }
        if (n == 0 || n == 1) return true;
        return func(head, n, 0);
    }

以上是关于[LeetCode刷题] - LC006 ZigZag Conversion的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode刷题-006Z字形变换

LeetCode刷题

算法刷题:LC初级算法

算法刷题:LC初级算法

算法如何刷题

算法刷题:LC初级算法