代码随想录训练营第三天打卡!

8、开发商买土地

力扣原题

题目简介:

​ 在一个城市区域内,被划分成了n * m个连续的区块,每个区块都拥有不同的权值,代表着其土地价值。目前,有两家开发公司,A 公司和 B 公司,希望购买这个城市区域的土地。

​ 现在,需要将这个城市区域的所有区块分配给 A 公司和 B 公司。

​ 然而,由于城市规划的限制,只允许将区域按横向或纵向划分成两个子区域,而且每个子区域都必须包含一个或多个区块。 为了确保公平竞争,你需要找到一种分配方式,使得 A 公司和 B 公司各自的子区域内的土地总价值之差最小。

​ 注意:区块不可再分。

初见思路:

​ well,我完全没有什么思路一开始,我想的就是把所有的情况都算出来,就是横向分把所有的情况算出来,然后竖向分把所有的情况算出来,然后比出最小值,但是实现起来真的漏洞百出,我发现自己的数组操作真的和筛子一样,到处都是越界。所以,这也是我坚持把这道题debug出来的原因,我一定要看看自己到底什么地方没有注意到越界的问题。

​ 但是最后,还是看了答案才写正确,笑死。

算法思路:

​ 我觉得算法的思路确实也是把情况都算出来然后再进行比较,但是有一点优化就是他用了前缀和的想法简化了每次的运算我觉得,但是他不是额外存了一个前缀和,而是临时计算了这一行或者一列划分时的前缀和,但其实都一样,计算量是一样的,在之前先算出来,还是后面再算其实都是算一次而已。

#include <iostream>
#include <vector>
#include <algorithm>


using namespace std;


int main(){
    
    int n ,m ;
    cin>>n>>m;
    int sum =0;
    vector<vector<int>> nums(n,vector<int>(m,0));
    for(int i = 0 ;i < n ;i++){
        for(int j = 0; j < m ; j++){
            cin>>nums[i][j];
            sum+=nums[i][j];
        }
    }
    vector<int> col_div(n,0);
    vector<int> row_div(m,0);
    
    
    for(int i = 0;i<n;i++){
        for(int j = 0;j<m;j++){
            col_div[i] = col_div[i] + nums[i][j];
        }
    }
    for(int j = 0;j<m;j++){
        for(int i = 0;i<n;i++){
            row_div[j] = row_div[j] + nums[i][j];
        }
    } 
    int col_temp =  0;
    int min_res = INT32_MAX;
    for(int i = 0 ; i < n ; i++){
            col_temp+= col_div[i];
            min_res = min(min_res, abs(sum - col_temp - col_temp));  
    }
    int row_temp= 0;
    for(int i = 0 ; i < m ; i++){
        row_temp+= row_div[i];
        min_res = min(min_res, abs(sum - row_temp - row_temp));    
    }
    cout<<min_res<<endl;
   
}

9、移除链表元素

力扣原题

题目简介:

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点

初见思路:

​ 这个题目知道,我自己的想法是,需要维护一个前节点pre,然后一个当前节点cur,这样子就可以在把当前节点cur去掉后,能够让precur->next联系起来;

​ 感觉有点像,你把自己当作当前节点的话,你就要知道前节点是什么才行;然后后面的那个方法就感觉是,把自己当作是前节点,那我就得知道我的下一节点的下一节点;嗯,就是这样。

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* vir_head = new ListNode();
        ListNode* prve = vir_head;
        ListNode* cur = head;

        vir_head->next = head;
        if( head != nullptr && head->val == val){
            vir_head->next = head->next;
            cur = vir_head->next;
            prve = vir_head;
        }
        while(cur != nullptr){

            if(cur->val == val){
                cur = cur->next;
                prve->next = cur;                    
            }
            else{
                prve = cur;
                cur =cur->next;
            }
        }
        return vir_head->next;
    }
};

​ 这个虚拟节点的方法真是妙呀,我一开始还不知道怎么处理头节点呢,只想到了先把头节点存起来这样;

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        

       
        while( head != nullptr && head->val == val){
            head = head->next;
        }

        ListNode *cur = head;

        while(cur!=nullptr){
            if(cur->next != nullptr && cur->next->val == val){
                cur->next = cur->next->next;
            }
            else{
                cur = cur->next;
            }

        }
        return head;
    }
};

​ 上面这个方法就是把自己当作前节点来思考了,比较关键的就是一定要先把头节点处理好,头节点不能是目标值所在的位置才行。

10、设计链表

力扣原题

题目简介:

你可以选择使用单链表或者双链表,设计并实现自己的链表。

单链表中的节点应该具备两个属性:valnextval 是当前节点的值,next 是指向下一个节点的指针/引用。

如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。

实现 MyLinkedList 类:

  • MyLinkedList() 初始化 MyLinkedList 对象。
  • int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1
  • void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
  • void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。
  • void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。
  • void deleteAtIndex(int index) 如果下标有效,则删除链表中下标为 index 的节点。

初见思路:

​ 救命,我想到了要自己顶一个node,然后我看要根据index来进行访问,所以我想着给每一个node安排一个成员index,然后遍历访问节点的index来达到按index访问元素的目的,结果…我完全不知道该怎么维护节点的index;还是算法中的while(n)妙!

class MyLinkedList {
public:

    struct LinkedNode{

        int val;
        LinkedNode* next;
        LinkedNode(int value) : val(value),next(nullptr) {  }
    };



    MyLinkedList() : size(0){
        dummyhead = new LinkedNode(0);
    }
    
    int get(int index) {
        if (index > (size - 1) || index < 0) {
            return -1;
        }
        LinkedNode* cur = dummyhead->next; // 这样子,cur直接从第1个节点开始,n次后就到了第n个节点
        
        while(index){
            cur= cur->next;
            index--;
        }
        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* cur = dummyhead;

        while(cur->next != nullptr){
            cur =  cur->next;
        }
        LinkedNode* node = new LinkedNode(val);
        cur->next = node;
        size++;
    }
    
    void addAtIndex(int index, int val) {
        if(index > size) return;
        if(index < 0) index = 0;   
        LinkedNode* cur = dummyhead;
        while(index){
            cur= cur->next;
            index--;
        }
        LinkedNode* node = new LinkedNode(val);
        node->next = cur->next;
        cur->next = node;
        size++;
    }
    
    void deleteAtIndex(int index) {
        if (index >= size || index < 0) {
            return;
        }
        LinkedNode* cur = dummyhead;// 这样子,cur直接从第0个节点开始,n次后就到了第n-1个节点
        while(index){               // cur->next 是第n个节点
            cur= cur->next;
            index--;
        }
        LinkedNode* tmp = cur->next;
        cur->next = cur->next->next;
        delete tmp;
        tmp = nullptr;
        size--;   
    }
    void printLinkedList() {
        LinkedNode* cur = dummyhead;
        while (cur->next != nullptr) {
            cout << cur->next->val << " ";
            cur = cur->next;
        }
        cout << endl;
    }

private:
    LinkedNode* dummyhead;
    int size;
};

/**
 * 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);
 */

​ 确实感觉自己对于链表的理解完善了一下,我觉得最妙的就是虚拟头节点了!

      LinkedNode* cur = dummyhead->next; // 这样子,cur直接从第1个节点开始,n次后就到了第n个节点
      LinkedNode* cur = dummyhead;// 这样子,cur直接从第0个节点开始,n次后就到了第n-1个节点

​ 这两个语句的运用真是出神入化!理顺了以后感觉一切都通畅了!
今天把昨天的开发商的题补了,但是又没时间写今天的第三题了,救命,明天一定补上!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值