天天看点

leetcode刷题笔记(1):简单题(链表)

leetcode刷题笔记(1):简单题(链表)C++

文章目录

    • leetcode刷题笔记(1):简单题(链表)C++
    • 141、环形链表
    • 160、相交链表
    • 203、移除链表元素
    • 206、反转链表
    • 225、用队列实现栈
    • 面试题10.01、合并排序的数组
    • 234、回文链表
    • 237、删除链表中的节点(智商题)
    • 326、3的幂
    • 344、反转字符串
    • 876、链表的中间结点
    • 1290、二进制链表转整数

141、环形链表

问题

给定一个链表,判断链表中是否有环。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

示例 1:

输入:head = [3,2,0,-4], pos = 1

输出:true

解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0

输出:true

解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入:head = [1], pos = -1

输出:false

解释:链表中没有环。

进阶:

你能用 O(1)(即,常量)内存解决此问题吗?

代码模板

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        
    }
};
           

题解

我的方法

遍历链表的同时,记录每一个节点指针,判断当前节点的

next

是否指向保存的节点指针列表。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        vector<ListNode*> tmp;  //用set更好!!!
        ListNode* cur=head;
        while(cur != NULL){
            tmp.push_back(cur);
            for(auto ptr : tmp){
                if(cur->next==ptr)
                    return true;
            }
            cur = cur->next;
        }
        return false;
    }
};
           
  • 时间复杂度O(N)
  • 空间复杂度O(N)

双指针O(1)法

通过使用具有 不同速度 的快、慢两个指针遍历链表,空间复杂度可以被降低至 O(1)O(1)。慢指针每次移动一步,而快指针每次移动两步。

如果列表中不存在环,最终快指针将会最先到达尾部,此时我们可以返回 false。

现在考虑一个环形链表,把慢指针和快指针想象成两个在环形赛道上跑步的运动员(分别称之为慢跑者与快跑者)。而快跑者最终一定会追上慢跑者。这是为什么呢?考虑下面这种情况(记作情况 A)- 假如快跑者只落后慢跑者一步,在下一次迭代中,它们就会分别跑了一步或两步并相遇。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(head==NULL || head->next==NULL)
            return false;
        ListNode* slow=head;
        ListNode* fast=head->next;
        while(fast != slow){
            if(fast==NULL || fast->next==NULL )
                return false;
            slow=slow->next;
            fast = fast->next->next;
        }
        return true;
    }
}; 
           
  • 时间复杂度O(N)
  • 空间复杂度O(1)

160、相交链表

题目

编写一个程序,找到两个单链表相交的起始节点。

leetcode刷题笔记(1):简单题(链表)

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3

输出:Reference of the node with value = 8

输入解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

题解

**first **

最笨的方法!!固定链表A,从链表B头节点开始,依次判断是否等于A中的节点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *cur = headA;
        while(cur != NULL){
            ListNode *tmp = headB;
            while(tmp != NULL){
                if(tmp==cur)
                    return tmp;
                tmp = tmp->next;
            }
            cur = cur->next;
        }
        return NULL;
    }
};
           
  • 时间复杂度O(NM)
  • 空间复杂度O(1)

second

先算出两个链表的长度,将长 的那个链表的指针ptr移动 AB长度差个单位,即使AB的当前指针对齐,当前指针的后面链表长度相等。再同时滑动两个指针,直至指针相等。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int la=0,lb=0;
        ListNode *ptrA = headA,*ptrB = headB;
        while(ptrA!=NULL){
            la++;
            ptrA = ptrA->next;
        }
        while(ptrB != NULL){
            lb++;
            ptrB = ptrB->next;
        }
        ptrA=headA;
        ptrB=headB;
        if(la>lb){
            for(int i=0;i<la-lb;i++)
                ptrA = ptrA->next;
        }
        if(lb>la){
            for(int i=0;i<lb-la;i++)
                ptrB = ptrB->next;
        }
        while(ptrA != ptrB){
            ptrA = ptrA->next;
            ptrB = ptrB->next;
        }
        return ptrA;
    }
};
           
  • 时间复杂度O(N+M)
  • 空间复杂度O(1)

浪漫————解法

错的人迟早会走散,而对的人迟早会相逢!

A和B两个链表长度可能不同,但是A+B和B+A的长度是相同的,所以遍历A+B和遍历B+A一定是同时结束。 如果A,B相交的话A和B有一段尾巴是相同的,所以两个遍历的指针一定会同时到达交点 如果A,B不相交的话两个指针就会同时到达A+B(B+A)的尾节点!

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* ptrA=headA,*ptrB = headB;
        while(ptrA != ptrB){
            ptrA = ptrA==NULL ? headB:ptrA->next;
            ptrB = ptrB==NULL ? headA:ptrB->next;
        }
        return ptrA;
    }
}; 
           
  • 时间复杂度 : O(m+n)
  • 空间复杂度 : O(1)

203、移除链表元素

题目

删除链表中等于给定值 val 的所有节点。

示例:

输入: 1->2->6->3->4->5->6, val = 6
输出: 1->2->3->4->5
           

题解

哨兵节点法

如果要删除的点位于链表头节点时,比较难操作,因此新建一个哨兵节点。

class Solution {
  public:
  ListNode* removeElements(ListNode* head, int val) {
    ListNode* sentinel = new ListNode(0);
    sentinel->next = head;

    ListNode *prev = sentinel, *curr = head, *toDelete = nullptr;
    while (curr != nullptr) {
      if (curr->val == val) {
        prev->next = curr->next;
        toDelete = curr;
      } else prev = curr;

      curr = curr->next;

      if (toDelete != nullptr) {
        delete toDelete;
        toDelete = nullptr;
      }
    }

    ListNode *ret = sentinel->next;
    delete sentinel;
    return ret;
  }
};
           
  • 时间复杂度O(N)
  • 空间复杂度O(1)

无需哨兵法

巧妙之处在于,先不管第一个节点,先把后面的去掉,最后只有第一个节点可能需要删除,不必考虑其他节点了;🐂🍺

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        if(!head)
            return nullptr;
        ListNode* p = head, *q;
        while(p->next)
        {
            if(p->next->val == val)
            {
                q = p->next;
                p->next = q->next;
                delete q;
            }
            else
                p = p->next;
        }
        return head->val == val ? head->next : head; //此处只需考虑第一个节点
    }
};
           
  • 时间复杂度O(N)
  • 空间复杂度O(1)

万事皆可递归法

无情递归

class Solution
{
    public ListNode removeElements(ListNode head, int val)
    {
        if (head == null)
            return head;
        head.next = removeElements(head.next, val);
        return head.val == val ? head.next : head;
    }
}
           
  • 空间复杂度O(N)
  • 时间复杂度O(N)

206、反转链表

题目

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
           

进阶:你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

题解

  • 我的方法

    使用

    last

    定位上一个节点,

    next

    定位下一个节点,

    cur

    定位当前节点,如果

    cur

    不为空,将

    cur->next

    指向上一节点,重新定位

    last

    ,使用

    next

    cur

    移动到下一节点,开始下一循环。
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* cur = head,*last=NULL,*next;
        while(cur != NULL)
        {
            next = cur->next;
            cur->next = last;
            last = cur;
            cur = next;
        }
        return last;
        
    }
};
           
  • 最短时间

使用了递归。将传入的链表分成两部分,第一个节点和剩余节点组成的链表,若要反转链表,只需反转第一个节点和剩余节点的反转链表;剩余节点的反转链表可以递归使用函数求出。

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(!head || !head ->next)
            return head;
        ListNode* newHead = reverseList(head ->next);
        head ->next ->next = head;
        head ->next = nullptr;
        return newHead;    
    }
};
           

225、用队列实现栈

题目

使用队列实现栈的下列操作:

push(x) – 元素 x 入栈

pop() – 移除栈顶元素

top() – 获取栈顶元素

empty() – 返回栈是否为空

注意:

你只能使用队列的基本操作-- 也就是 push to back, peek/pop from front, size, 和 is empty 这些操作是合法的。

你所使用的语言也许不支持队列。 你可以使用 list 或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)。

题解

题意应该是让用单向队列来解决的,有些题解直接用的双向队列,鄙视!!

单向队列也很简单,唯一需要注意的是

push

操作,栈需要在栈顶

push

,而队列只能一头

pop

,一头

push

,我用的是队首当栈顶,因此队列

push

的时候,需要依次把队首的元素插到队尾,从而使新

push

的元素处于队首,也就是栈顶。

class MyStack {
private:
    queue<int> q;
public:
    /** Initialize your data structure here. */
    MyStack() {
                  
    }
    
    /** Push element x onto stack. */
    void push(int x) {
        q.push(x);
        for(int i=0;i<q.size()-1;i++){
            q.push(q.front());
            q.pop();
        }
    }
    
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        int x=q.front();
        q.pop();
        return x;
    }
    
    /** Get the top element. */
    int top() {
        return q.front();
    }
    
    /** Returns whether the stack is empty. */
    bool empty() {
        return q.empty();
    }
};

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack* obj = new MyStack();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->top();
 * bool param_4 = obj->empty();
 */
           

面试题10.01、合并排序的数组

题目

给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法,将 B 合并入 A 并排序。

初始化 A 和 B 的元素数量分别为 m 和 n。

示例:

输入:

A = [1,2,3,0,0,0], m = 3

B = [2,5,6], n = 3

输出: [1,2,2,3,5,6]

说明:

A.length == n + m

题解

投机取巧(鄙视我自己解法):用C++自带的

sort

算法求解。(

insert

是插入,会造成A的空间变大,A中的0并不会消失,因此使用

resize

重新分配A的空间)

class Solution {
public:
    void merge(vector<int>& A, int m, vector<int>& B, int n) {
        A.insert(A.begin()+m,B.begin(),B.end());
        A.resize(m+n);
        sort(A.begin(),A.end());
    }
};
           
  • 时间复杂度:O((m+n)\log(m+n))

    排序序列长度为 m+n,套用快速排序的时间复杂度即可,平均情况为 O((m+n)\log(m+n))

  • 空间复杂度:O(\log(m+n))

    排序序列长度为 m+n,套用快速排序的空间复杂度即可,平均情况为 O(\log(m+n))

解法二:

反向排序,先排最大的;因此A后面又足够的位置,以至于A不会被覆盖元素

class Solution {
public:
    void merge(vector<int>& A, int m, vector<int>& B, int n) {
        int pa = m - 1, pb = n - 1;
        int tail = m + n - 1;
        int cur;
        while (pa >= 0 || pb >= 0) {
            if (pa == -1)
                cur = B[pb--];
            else if (pb == -1)
                cur = A[pa--];
            else if (A[pa] > B[pb])
                cur = A[pa--];
            else
                cur = B[pb--];
            A[tail--] = cur;
        }
    }
};
           
  • 时间复杂度:O(m+n)

    指针移动单调递减,最多移动 m+nm+n 次,因此时间复杂度为 O(m+n)

  • 空间复杂度:O(1)

    直接对数组 A 原地修改,不需要额外空间

234、回文链表

问题

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

示例 1:

输入: 1->2

输出: false

示例 2:

输入: 1->2->2->1

输出: true

进阶:

你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

题解

笨方法

修改链表结构,使前一半反向,再遍历两个半链表!修改了链表一般不可取!!!

所以修改了输入的链表一般使用完,要恢复的原来的结构。(我懒的改回去了)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if(head==NULL || head->next == NULL)
            return true;
        int l=0;
        ListNode* ptr = head;
        while(ptr != NULL){
            l++;
            ptr = ptr->next;
        }
        ptr = head;
        ListNode *tmp=NULL,*tmp1 = head;
        for(int i=0;i<l/2;i++){
            ptr = tmp1;
            tmp1 = ptr->next;
            ptr->next = tmp;
            tmp  = ptr;
            
        }
        tmp1 = l%2==0?tmp1:tmp1->next;
        while(ptr != NULL ){
            if(ptr->val != tmp1->val)
                return false;
            ptr = ptr->next;
            tmp1 = tmp1->next;
        }
        return true;
    }
};
           
  • 时间复杂度O(N)
  • 空间复杂度O(1)

黄金升级版

应用了快慢指针法,再遍历的同时,使链表的前一半逆向。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if(!head||!head->next) return true;
        auto fast=head,slow=head;
        ListNode* p,*pre=NULL;
        while(fast&&fast->next){
            p=slow;
            slow=slow->next;
            fast=fast->next->next;
            p->next=pre;
            pre=p;
        }
        if(fast) slow=slow->next;
        while(p){
            if(p->val!=slow->val) return false;
            p=p->next;
            slow=slow->next;
        }
        return true;
    }
};
           
  • 时间复杂度O(N)
  • 空间复杂度O(1)

237、删除链表中的节点(智商题)

问题

请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。

  • 示例 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.

代码模板

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
        
    }
};
           

提示

引用一个评论:

这道题细思极恐:如何让自己在世界上消失,但又不死? —— 将自己完全变成另一个人,再杀了那个人就行了。

           

题解

无语题,这题出的,不就是数组删除节点的做法吗?(只给了

ListNode* node

要删除的节点,其他一律没有!!)

my way

我是把之后的节点依次复制到前一节点,最后删除最后一个节点。

然而我这做法也笨了,思路窄了窄了!!

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
        while(node->next->next != NULL){
            node->val = node->next->val;
            node = node->next;
        }
        ListNode* tmp = node->next;;
        node->val = node->next->val;
        node->next = NULL;
        delete tmp;
    }
};
           
  • 时间复杂度O(N)
  • 空间复杂度O(1)

好一点的方法

比我的好多了!!

只将下一节点复制到要删除的节点,然后当前节点跳到下下节点,删除下一节点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
        node->val = node->next->val;
        ListNode *tmp = node->next;
        node->next = tmp->next;
        delete tmp;
    }
};
           
  • 时间复杂度O(1)
  • 空间复杂度O(1)

326、3的幂

问题

给定一个整数,写一个函数来判断它是否是 3 的幂次方。

示例 1:

输入: 27
输出: true
示例 2:

输入: 0
输出: false
示例 3:

输入: 9
输出: true
           

题解

我的辣子鸡方法

class Solution {
public:
    bool isPowerOfThree(int n) {
        for(int i=0;i<n;i++){
            if(pow(3,i) == n)
                return true;
            if(pow(3,i)> n)
                return false;
        }
        return false;
        
    }
};
           
  • 时间复杂度O(N) :将pow复杂度视为O(1),可能不太对
  • 空间复杂度O(1)

无情递归

不会做就递归系列

class Solution {
public:
    bool isPowerOfThree(int n) {
        if (n==1)
            return true;
        else if (n>0 && n%3==0)
            return isPowerOfThree(n/3);
        else
            return false;
    }
};
           
  • 时间复杂度O(N)
  • 空间复杂度O(N)

循环迭代法

class Solution {
public:
    bool isPowerOfThree(int n) {
        if (n < 1) {
            return false;
        }
        while (n % 3 == 0) {
            n /= 3;
        }
        return n == 1;
    }
}
           
  • 时间复杂度:O(log_b(n))。除数是用对数表示的。

    空间复杂度:O(1),没有使用额外的空间。

整数限制

无法言语

可以看出 n 的类型是 int。在 Java 中说明了该变量是四个字节,他的最大值为 2147483647。有三种方法可以计算出该最大值。

Google

System.out.println(Integer.MAX_VALUE);

MaxInt = 2^{32} /2-1,因为我们使用 32 位来表示数字,所以范围的一半用于负数,0 是正数的一部分。

知道了 n 的限制,我们现在可以推断出 n 的最大值,也就是 3 的幂,是 1162261467。

class Solution {
public:
    bool isPowerOfThree(int n) {
        return n > 0 && 1162261467 % n == 0;
    }
}
           
  • 时间复杂度O(1)
  • 空间复杂度 O(1)

344、反转字符串

题目

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

示例 1:
输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]
示例 2:

输入:["H","a","n","n","a","h"]
输出:["h","a","n","n","a","H"]
           

题解

my way

很简单,用一个

char

的额外空间即可。两头互相交换,直到相遇。

class Solution {
public:
    void reverseString(vector<char>& s) {
        char tmp;
        for(int i=0;i<s.size()/2;i++){
            tmp=s[i];
            s[i]=s[s.size()-i-1];
            s[s.size()-1-i]=tmp;
        }
    }
};
           
  • 空间复杂度 O(1) 只是用了一个额外空间
  • 时间复杂度O(n) 一次循环交换2个值,因此最多有n/2次交换,因此为O(n)

最简洁方法

使用自带算法(耍赖),

class Solution {
public:
    void reverseString(vector<char>& s) {
        reverse(s.begin(),s.end());
    }
};
           
  • 空间复杂度 ??
  • 时间复杂度 ??

递归

递归需要堆栈空间

class Solution {
public:
    void reverseString(vector<char>& s) {
        
        helper(s, 0, s.size());

    }
    
    void helper(vector<char>& s, int pos, int s_len){
        if ( pos >= s_len / 2) return;
        char tmp = s[pos];
        s[pos] = s[s_len - 1 - pos];
        s[s_len - 1 - pos ] = tmp;
        
        helper(s, pos+1, s_len);
    }
};
           
  • 空间复杂度O(N) 执行了N/2次交换
  • 时间复杂度O(N).递归过程中使用了堆栈空间

876、链表的中间结点

题目

给定一个带有头结点 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

示例 1:

输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
示例 2:

输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。
           

题解

快慢指针法

根据141题的快慢指针法来的灵感

好吧,其实一模一样的解法,不过更简单点

两个指针,一个一次走一步,另一个一次走两步,当块的那个走到结尾的时候,慢的指针正好走到一半

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* middleNode(ListNode* head) {
        ListNode* slow=head;
        ListNode* fast=head;
        while(true){
            if(fast==NULL || fast->next==NULL)
                return slow;
            slow = slow->next;
            fast = fast->next->next;
        }
    }
};
           
  • 时间复杂度O(N)
  • 空间复杂度O(1)

单指针法

先遍历一次,求得链表长度,在遍历一半即可

class Solution {
public:
    ListNode* middleNode(ListNode* head) {
        int n = 0;
        ListNode* cur = head;
        while (cur != nullptr) {
            ++n;
            cur = cur->next;
        }
        int k = 0;
        cur = head;
        while (k < n / 2) {
            ++k;
            cur = cur->next;
        }
        return cur;
    }
};
           
  • 时间复杂度O(N)
  • 空间复杂度O(1)

1290、二进制链表转整数

题目

给你一个单链表的引用结点 head。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。

请你返回该链表所表示数字的 十进制值 。

示例 1:
输入:head = [1,0,1]
输出:5
解释:二进制数 (101) 转化为十进制数 (5)
示例 2:

输入:head = [0]
输出:0
示例 3:

输入:head = [1]
输出:1
示例 4:

输入:head = [1,0,0,1,0,0,1,1,1,0,0,0,0,0,0]
输出:18880
示例 5:

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

提示:

链表不为空。
链表的结点总数不超过 30。
每个结点的值不是 0 就是 1。
           

题解

简单的不能再简单的移位操作

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    int getDecimalValue(ListNode* head) {
        int d=0;
        ListNode* ptr = head;
        while(ptr != NULL){
            d = d*2+ptr->val;
            ptr = ptr->next;
        }
        return d;
    }
};
           
  • 时间复杂度O(N)
  • 空间复杂度O(1)