代码随想录算法训练营刷题复习11:数组、链表题目复习

数组

双指针用的比较多

  1. 704. 二分查找
  2. 27. 移除元素
  3. 977. 有序数组的平方
  4. 209. 长度最小的子数组
    滑动窗口
  5. 59. 螺旋矩阵 II
    !! 需要再复习

704. 二分查找

class Solution {
public:
    int search(vector<int>& nums, int target) {
        // int left = 0;
        // int right = nums.size()-1;

        // while(left<=right) {
        //     int mid = left+(right-left)/2;
        //     if(nums[mid] > target) {
        //         right = mid-1;
        //     }
        //     else if(nums[mid] < target) {
        //         left = mid+1;
        //     }
        //     else
        //         return mid;
        // }
        // return -1;
//for循环就不用指定i++ j--了,在if判断中已经添加了对i j 的处理
        for(int i=0,j=nums.size()-1;i<=j;) {
            int mid = i+((j-i)/2);
            if(nums[mid]==target)
                return mid;
            else if(nums[mid]<target) {
                i=mid+1;
            }
            else if(nums[mid]>target) {
                j=mid-1;
            }

        }
        return -1;
    }
};

27. 移除元素

快慢指针,一遍过

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int i,j=0;
        for(i=0;i<nums.size();i++) {
            if(nums[i]!=val) {
                nums[j]=nums[i];
                j++;
            }
            if(nums[i]==val) {
                continue;
            }
        }
        return j;
    }
};

977. 有序数组的平方

借助sort

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        for(int i=0;i<nums.size();i++) {
            nums[i]*=nums[i];
        }
        sort(nums.begin(),nums.end());
        return nums;
    }
};

不用sort

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int k=nums.size()-1;
        vector<int> res(nums.size(),0);

        //原先的数组是非递减顺序,遇到绝对值大的负值 平方后会改变位置
        //使用双指针控制存入新数组的大小顺序
        for(int i=0,j=nums.size()-1;i<=j) {
            if(nums[i]*nums[i] < nums[j]*nums[j]){
                res[k] = nums[j]*nums[j];
                k--;
                j--;
            }
            else {
                res[k] = nums[i]*nums[i];
                k--;
                i++;
            }
        }
        return res;
    }
};

209. 长度最小的子数组

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int i=0,j=0;
        int sum=0;
        int count=nums.size()+1;
        for(int i=0,j=0;i<nums.size();i++) {
            sum+=nums[i];
            while(sum>=target) {
                count = count < (i-j+1) ? count : (i-j+1);
                sum-=nums[j++]; 
            }
        }
        return count == nums.size()+1 ? 0 : count;
    }
};

59. 螺旋矩阵 II
!!

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
        int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
        int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
        int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
        int count = 1; // 用来给矩阵中每一个空格赋值
        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
        int i,j;
        while (loop --) {
            i = startx;
            j = starty;

            // 下面开始的四个for就是模拟转了一圈
            // 模拟填充上行从左到右(左闭右开)
            for (j; j < n - offset; j++) {
                res[i][j] = count++;
            }
            // 模拟填充右列从上到下(左闭右开)
            for (i; i < n - offset; i++) {
                res[i][j] = count++;
            }
            // 模拟填充下行从右到左(左闭右开)
            for (; j > starty; j--) {
                res[i][j] = count++;
            }
            // 模拟填充左列从下到上(左闭右开)
            for (; i > startx; i--) {
                res[i][j] = count++;
            }

            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
            startx++;
            starty++;

            // offset 控制每一圈里每一条边遍历的长度
            offset += 1;
        }

        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
        if (n % 2) {
            res[mid][mid] = count;
        }
        return res;
    }
};

链表

大部分的题来说,定义一个虚拟头节点能够有助于处理链表操作。

删除操作大多需要pre来保存前一节点的状态

环形链表这个题时间长又忘了怎么解了

  1. 203. 移除链表元素
  2. 707. 设计链表
    此题不熟
  3. 206. 反转链表
    头插法
  4. 19. 删除链表的倒数第 N 个结点
    ①记录链表长度,找到倒数第n个节点的下标
    ②pre 和 cur
  5. 面试题 02.07. 链表相交
    ①统计两链表的长度
    ②统一长度后两链表一起遍历判断节点是否相等
  6. 142. 环形链表 II
    !!! 快慢指针,时间久又有点忘记了。

203. 移除链表元素
①虚拟头结点dummyHead;
②用一temp来遍历链表所有节点
③链表删除节点的逻辑…太熟了不写了

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode* temp = dummyHead;
        while(temp->next != NULL) {
            if(temp->next->val == val) {
                ListNode* node = temp->next;
                temp->next = temp->next->next;
                delete node;
            } else {
                temp = temp->next;
            }
        }
        head = dummyHead->next;
        delete dummyHead;
        return head;
    }
};

707. 设计链表
此题不熟

class MyLinkedList {

public:
    struct LinkedNode {
        int val;
        LinkedNode* next;
        LinkedNode(int val):val(val),next(nullptr) {}
    };
    MyLinkedList() {
        _dummyHead = new LinkedNode(0);
        _size=0;
    }
    
    int get(int index) {
        if(index > (_size-1) || index < 0) 
            return -1;
        LinkedNode* cur = _dummyHead->next;
        while(index--) {
            cur = cur->next;
        }
        return cur->val;
    }
    
    void addAtHead(int val) {
        LinkedNode* node = new LinkedNode(val);
        node->next = _dummyHead->next;
        _dummyHead->next = node;
        _size++;
    }
    
    void addAtTail(int val) {
        LinkedNode* node = new LinkedNode(val);
        LinkedNode* cur = _dummyHead;
        while(cur->next!=nullptr) {
            cur = cur->next;
        }
        cur->next = node;
        _size++;
    }
    
    void addAtIndex(int index, int val) {
        if(index > _size)
            return;
        if(index < 0)
            index=0;
        LinkedNode* node = new LinkedNode(val);
        LinkedNode* cur = _dummyHead;
        while(index--) {
            cur = cur->next;
        }
        node->next = cur->next;
        cur->next = node;
        _size++;
    }
    
    void deleteAtIndex(int index) {
        if(index >= _size || index<0)
            return;
        LinkedNode* cur = _dummyHead;
        while(index--) {
            cur = cur->next;
        }
        LinkedNode* node = cur->next;
        cur->next = cur->next->next;
        delete node;
        node = nullptr;
        _size--;
    }

private:
    int _size;
    LinkedNode* _dummyHead;
};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList* obj = new MyLinkedList();
 * int param_1 = obj->get(index);
 * obj->addAtHead(val);
 * obj->addAtTail(val);
 * obj->addAtIndex(index,val);
 * obj->deleteAtIndex(index);
 */

206. 反转链表
头插法

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = nullptr;

        ListNode* cur = head;
        while(cur!=nullptr) {
            ListNode* node = new ListNode(0);
            node->val = cur->val;
            node->next = dummyHead->next;
            dummyHead->next = node;
            cur = cur->next;
        }
        return dummyHead->next;
    }
};

19. 删除链表的倒数第 N 个结点
①记录链表长度,找到倒数第n个节点的下标
②pre 和 cur

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        if(head == nullptr)
            return head;
        else if(head->next==nullptr && n==1)
            return nullptr;
        ListNode* tail = head;
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        int size = 0;
        while(tail!=nullptr) {
            tail = tail->next;
            size++;
        }
        ListNode* cur = head;
        ListNode* pre = dummyHead;
        pre->next = cur;
        int a = size-n;
        while(a-- && cur!=nullptr) {
            pre = cur;
            cur = cur->next;
        }
        ListNode* temp = cur;
        pre->next = cur->next;
        delete temp;

        return dummyHead->next;
    }
};

面试题 02.07. 链表相交

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* curA = headA;
        ListNode* curB = headB;
        int sizeA = 0, sizeB = 0;
        while(curA!=nullptr) {
            sizeA++;
            curA = curA->next;
        }
        while(curB!=nullptr) {
            sizeB++;
            curB = curB->next;
        }
        curA = headA;
        curB = headB;
        if(sizeA > sizeB) {
            int a = sizeA - sizeB;
            while(a--) {
                curA=curA->next;
            }
        }
        
        else if(sizeA < sizeB) {
            int b = sizeB - sizeA;
            while(b--) {
                curB=curB->next;
            }
        }
        while(curA != nullptr && curB != nullptr)
        {
            if(curA == curB)
                return curA;
            else
            {
                curA = curA->next;
                curB = curB->next;
            }
        }
        return nullptr;
    }
};

142. 环形链表 II
快慢指针,时间久又有点忘记了。

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast!=nullptr && fast->next!=nullptr) {
            slow = slow->next;
            fast = fast->next->next;
            if(slow == fast) {
                ListNode* index1 = head;
                ListNode* index2 = fast;
                while(index1!=index2) {
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index2;
            }
        }
        return nullptr;
    }
};
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值