编程日志4.21

单链表部分题目

1.Problem - 1092

#include
#include

using namespace std;
#define eleType int


struct ListNode {
    eleType data;//定义eleType类型的变量data,用于存储结点的数据域
    ListNode* next;//定义了一个指向ListNode结构体类型的指针域next,用于指向链表的下一个结点
    ListNode(eleType x) :data(x), next(NULL) {}
    //ListNode结构体的构造函数。它接受一个eleType类型的参数x,并将其值赋值给结点的数据成员data。同时,将next指针初始化为NULL,表示当前结点为链表的末尾结点。
};

//单向链表类
class LinkedList {
private:
    ListNode* head;//定义链表的头结点
    int size;//定义链表的大小
public:
    LinkedList() :head(NULL), size(0) {}//链表的构造函数,初始化为一个空链表,链表元素个数为0
    ~LinkedList();//链表的析构函数,用于释放在堆上申请的空间
    void insert(int i, eleType value);//在链表的第i个位置,插入一个值为value的结点
    void remove(int i);//删除链表第i个位置的结点
    ListNode* find(eleType value);//查找链表中值为value的结点
    ListNode* get(int i);//获取链表中第i个位置的结点
    void update(int i, eleType valude);//修改链表中第i个位置的结点的值为value
    void print();//打印链表内容
    eleType sum();//求链表中所有元素的和
};

//链表的销毁
LinkedList::~LinkedList() {
    ListNode* curr = head;
    while (curr != NULL) {//从链表的头结点开始,不断往后遍历
        ListNode* temp = curr;
        curr = curr->next;
        delete temp;//每次遍历完,将它存储在temp中,并利用delete释放对应地址的内存
    }
}

//链表的元素插入
void LinkedList::insert(int i, eleType value) {
    if (i<0 || i>size) {//检查插入位置i是否有效
        throw std::out_of_range("Invalid position");
    }
    ListNode* newNode = new ListNode(value);//创建一个信的ListNode结点,并将给定的值赋给它的数据成员data、

    if (i == 0) {//i=0表示要在链表头部插入新结点
        newNode->next = head;
        head = newNode;
    }
    else {
        ListNode* curr = head;//初始化一个指针curr,并将其指向链表的头结点head,然后不断往后遍历链表,总共遍历i-1次

        for (int j = 0; j < i - 1; j++) {
            curr = curr->next;
        }
        newNode->next = curr->next;//将新结点的next指针设置为当前结点curr的next指针所指向的结点,这样新结点就被插入l当前结点之后
        curr->next = newNode;//将当前结点curr的next指针指向新结点newNode,完成插入操作
    }
    size++;//链表大小加一
}

//链表的元素删除
void LinkedList::remove(int i) {
    if (i < 0 || i >= size) {//检查删除位置i是否有效
        throw std::out_of_range("Invalid position");
    }
    if (i == 0) {//如果i=0,表示要删除表头结点。这种情况下,将头结点head的next指针指向自身的后一个结点,然后删除圆头结点temp
        ListNode* temp = head;
        head = head->next;
        delete temp;
    }
    else {//如果i不等于0,表示要删除链表中的第i个结点。通过一个循环,将指针curr移动到第i-1个结点
        ListNode* curr = head;
        for (int j = 0; j < i - 1; j++) {
            curr = curr->next;
        }
        ListNode* temp = curr->next;//将第i个结点存储在临时变量temp中
        curr->next = temp->next;//将第i结点的next指针指向第i+1个结点
        delete temp;//删除第i个结点
    }
    size--;
}

//链表的元素查找
ListNode* LinkedList::find(eleType value) {
    ListNode* curr = head;
    while (curr != NULL && curr->data != value) {//从链表的头结点开始遍历,如果没到链表结尾,或者当前遍历到的结点和给定的值value不相等,则继续遍历
        curr = curr->next;//不断向后遍历的过程
    }
    return curr;//当curr为空或curr->data和value相等时,跳出循环,这时候返回curr就是找到的元素值相等的链表结点
}

//链表的元素索引
ListNode* LinkedList::get(int i) {
    if (i < 0 || i >= size) {//检查获取位置i是否有效
        throw std::out_of_range("Invalid position");
    }
    ListNode* curr = head;//初始化一个指针curr,并将其指向链表的头结点head
    for (int j = 0; j < i; ++j) {//将curr移动到链表中第i个位置之前的结点。
        curr = curr->next;//每次循环中,将curr的next指针指向当前结点的下一个结点
    }
    return curr;//返回第i个位置结点的指针curr
}

//链表的元素修改
void LinkedList::update(int i, eleType value) {
    if (i < 0 || i >= size) {
        throw std::out_of_range("Invalid position");
    }
    get(i)->data = value;//通过get函数索引到第i个链表结点,然后对data直接进行赋值操作
}

//链表的打印
void LinkedList::print() {
    ListNode* curr = head;
    while (curr != NULL) {//遍历整个链表,遍历的过程中顺便打印data的值
        cout << curr->data << " ";
        curr = curr->next;
    }
    cout << endl;
}

eleType LinkedList::sum() {
    ListNode* curr = head;
    eleType ret = 0;
    while (curr != NULL) {
        ret += curr->data;
        curr = curr->next;
    }
    return ret;
}

//主函数
int main() {
    int n;
    while (cin >> n && n){//一定要注意这个条件 为0终止
        LinkedList l;
        for (int i = 0; i < n; ++i) {
            int x;
            cin >> x;
            l.insert(i, x);
        }
        //l.print();检验正确输入部分
        cout << l.sum() << endl;
    }
    return 0;
}

2.Problem - 2041

#include
#include

using namespace std;
#define eleType int


struct ListNode {
    eleType data;//定义eleType类型的变量data,用于存储结点的数据域
    ListNode* next;//定义了一个指向ListNode结构体类型的指针域next,用于指向链表的下一个结点
    ListNode(eleType x) :data(x), next(NULL) {}
    //ListNode结构体的构造函数。它接受一个eleType类型的参数x,并将其值赋值给结点的数据成员data。同时,将next指针初始化为NULL,表示当前结点为链表的末尾结点。
};

//单向链表类
class LinkedList {
private:
    ListNode* head;//定义链表的头结点
    int size;//定义链表的大小
public:
    LinkedList() :head(NULL), size(0) {}//链表的构造函数,初始化为一个空链表,链表元素个数为0
    ~LinkedList();//链表的析构函数,用于释放在堆上申请的空间
    void insert(int i, eleType value);//在链表的第i个位置,插入一个值为value的结点
    void remove(int i);//删除链表第i个位置的结点
    ListNode* find(eleType value);//查找链表中值为value的结点
    ListNode* get(int i);//获取链表中第i个位置的结点
    void update(int i, eleType valude);//修改链表中第i个位置的结点的值为value
    void print();//打印链表内容
    eleType sum();//求链表中所有元素的和
};

//链表的销毁
LinkedList::~LinkedList() {
    ListNode* curr = head;
    while (curr != NULL) {//从链表的头结点开始,不断往后遍历
        ListNode* temp = curr;
        curr = curr->next;
        delete temp;//每次遍历完,将它存储在temp中,并利用delete释放对应地址的内存
    }
}

//链表的元素插入
void LinkedList::insert(int i, eleType value) {
    if (i<0 || i>size) {//检查插入位置i是否有效
        throw std::out_of_range("Invalid position");
    }
    ListNode* newNode = new ListNode(value);//创建一个信的ListNode结点,并将给定的值赋给它的数据成员data、

    if (i == 0) {//i=0表示要在链表头部插入新结点
        newNode->next = head;
        head = newNode;
    }
    else {
        ListNode* curr = head;//初始化一个指针curr,并将其指向链表的头结点head,然后不断往后遍历链表,总共遍历i-1次

        for (int j = 0; j < i - 1; j++) {
            curr = curr->next;
        }
        newNode->next = curr->next;//将新结点的next指针设置为当前结点curr的next指针所指向的结点,这样新结点就被插入l当前结点之后
        curr->next = newNode;//将当前结点curr的next指针指向新结点newNode,完成插入操作
    }
    size++;//链表大小加一
}

//链表的元素删除
void LinkedList::remove(int i) {
    if (i < 0 || i >= size) {//检查删除位置i是否有效
        throw std::out_of_range("Invalid position");
    }
    if (i == 0) {//如果i=0,表示要删除表头结点。这种情况下,将头结点head的next指针指向自身的后一个结点,然后删除圆头结点temp
        ListNode* temp = head;
        head = head->next;
        delete temp;
    }
    else {//如果i不等于0,表示要删除链表中的第i个结点。通过一个循环,将指针curr移动到第i-1个结点
        ListNode* curr = head;
        for (int j = 0; j < i - 1; j++) {
            curr = curr->next;
        }
        ListNode* temp = curr->next;//将第i个结点存储在临时变量temp中
        curr->next = temp->next;//将第i结点的next指针指向第i+1个结点
        delete temp;//删除第i个结点
    }
    size--;
}

//链表的元素查找
ListNode* LinkedList::find(eleType value) {
    ListNode* curr = head;
    while (curr != NULL && curr->data != value) {//从链表的头结点开始遍历,如果没到链表结尾,或者当前遍历到的结点和给定的值value不相等,则继续遍历
        curr = curr->next;//不断向后遍历的过程
    }
    return curr;//当curr为空或curr->data和value相等时,跳出循环,这时候返回curr就是找到的元素值相等的链表结点
}

//链表的元素索引
ListNode* LinkedList::get(int i) {
    if (i < 0 || i >= size) {//检查获取位置i是否有效
        throw std::out_of_range("Invalid position");
    }
    ListNode* curr = head;//初始化一个指针curr,并将其指向链表的头结点head
    for (int j = 0; j < i; ++j) {//将curr移动到链表中第i个位置之前的结点。
        curr = curr->next;//每次循环中,将curr的next指针指向当前结点的下一个结点
    }
    return curr;//返回第i个位置结点的指针curr
}

//链表的元素修改
void LinkedList::update(int i, eleType value) {
    if (i < 0 || i >= size) {
        throw std::out_of_range("Invalid position");
    }
    get(i)->data = value;//通过get函数索引到第i个链表结点,然后对data直接进行赋值操作
}

//链表的打印
void LinkedList::print() {
    ListNode* curr = head;
    while (curr != NULL) {//遍历整个链表,遍历的过程中顺便打印data的值
        cout << curr->data << " ";
        curr = curr->next;
    }
    cout << endl;
}

eleType LinkedList::sum() {
    ListNode* curr = head;
    eleType ret = 0;
    while (curr != NULL) {
        ret += curr->data;
        curr = curr->next;
    }
    return ret;
}

//主函数
int main() {
    LinkedList f;
    f.insert(0, 1);
    f.insert(1, 1);
    f.insert(2, 1);
    for (int i = 3; i <= 40; ++i) {
        ListNode* a = f.get(i - 1);//得到的是结点
        ListNode* b = f.get(i - 2);
        f.insert(i, a->data + b->data);//a->data得到数据
    }
    //f.print();数据测试代码
    int n;
    cin >> n;
    while (n--) {
        int x;
        cin >> x;
        cout << f.get(x)->data << endl;
    }
    return 0;
}

3.Problem - 2019

#include
#include

using namespace std;
#define eleType int


struct ListNode {
    eleType data;//定义eleType类型的变量data,用于存储结点的数据域
    ListNode* next;//定义了一个指向ListNode结构体类型的指针域next,用于指向链表的下一个结点
    ListNode(eleType x) :data(x), next(NULL) {}
    //ListNode结构体的构造函数。它接受一个eleType类型的参数x,并将其值赋值给结点的数据成员data。同时,将next指针初始化为NULL,表示当前结点为链表的末尾结点。
};

//单向链表类
class LinkedList {
private:
    ListNode* head;//定义链表的头结点
    int size;//定义链表的大小
public:
    LinkedList() :head(NULL), size(0) {}//链表的构造函数,初始化为一个空链表,链表元素个数为0
    ~LinkedList();//链表的析构函数,用于释放在堆上申请的空间
    void insert(int i, eleType value);//在链表的第i个位置,插入一个值为value的结点
    void remove(int i);//删除链表第i个位置的结点
    ListNode* find(eleType value);//查找链表中值为value的结点
    ListNode* get(int i);//获取链表中第i个位置的结点
    void update(int i, eleType valude);//修改链表中第i个位置的结点的值为value
    void print();//打印链表内容
    eleType sum();//求链表中所有元素的和
    void append(eleType);//插入元素到链表尾部
    void ascInsert(eleType value);//按照递增顺序进行插入
};

//链表的销毁
LinkedList::~LinkedList() {
    ListNode* curr = head;
    while (curr != NULL) {//从链表的头结点开始,不断往后遍历
        ListNode* temp = curr;
        curr = curr->next;
        delete temp;//每次遍历完,将它存储在temp中,并利用delete释放对应地址的内存
    }
}

//链表的元素插入
void LinkedList::insert(int i, eleType value) {
    if (i<0 || i>size) {//检查插入位置i是否有效
        throw std::out_of_range("Invalid position");
    }
    ListNode* newNode = new ListNode(value);//创建一个信的ListNode结点,并将给定的值赋给它的数据成员data、

    if (i == 0) {//i=0表示要在链表头部插入新结点
        newNode->next = head;
        head = newNode;
    }
    else {
        ListNode* curr = head;//初始化一个指针curr,并将其指向链表的头结点head,然后不断往后遍历链表,总共遍历i-1次

        for (int j = 0; j < i - 1; j++) {
            curr = curr->next;
        }
        newNode->next = curr->next;//将新结点的next指针设置为当前结点curr的next指针所指向的结点,这样新结点就被插入l当前结点之后
        curr->next = newNode;//将当前结点curr的next指针指向新结点newNode,完成插入操作
    }
    size++;//链表大小加一
}

//链表的元素删除
void LinkedList::remove(int i) {
    if (i < 0 || i >= size) {//检查删除位置i是否有效
        throw std::out_of_range("Invalid position");
    }
    if (i == 0) {//如果i=0,表示要删除表头结点。这种情况下,将头结点head的next指针指向自身的后一个结点,然后删除圆头结点temp
        ListNode* temp = head;
        head = head->next;
        delete temp;
    }
    else {//如果i不等于0,表示要删除链表中的第i个结点。通过一个循环,将指针curr移动到第i-1个结点
        ListNode* curr = head;
        for (int j = 0; j < i - 1; j++) {
            curr = curr->next;
        }
        ListNode* temp = curr->next;//将第i个结点存储在临时变量temp中
        curr->next = temp->next;//将第i结点的next指针指向第i+1个结点
        delete temp;//删除第i个结点
    }
    size--;
}

//链表的元素查找
ListNode* LinkedList::find(eleType value) {
    ListNode* curr = head;
    while (curr != NULL && curr->data != value) {//从链表的头结点开始遍历,如果没到链表结尾,或者当前遍历到的结点和给定的值value不相等,则继续遍历
        curr = curr->next;//不断向后遍历的过程
    }
    return curr;//当curr为空或curr->data和value相等时,跳出循环,这时候返回curr就是找到的元素值相等的链表结点
}

//链表的元素索引
ListNode* LinkedList::get(int i) {
    if (i < 0 || i >= size) {//检查获取位置i是否有效
        throw std::out_of_range("Invalid position");
    }
    ListNode* curr = head;//初始化一个指针curr,并将其指向链表的头结点head
    for (int j = 0; j < i; ++j) {//将curr移动到链表中第i个位置之前的结点。
        curr = curr->next;//每次循环中,将curr的next指针指向当前结点的下一个结点
    }
    return curr;//返回第i个位置结点的指针curr
}

//链表的元素修改
void LinkedList::update(int i, eleType value) {
    if (i < 0 || i >= size) {
        throw std::out_of_range("Invalid position");
    }
    get(i)->data = value;//通过get函数索引到第i个链表结点,然后对data直接进行赋值操作
}

//链表的打印
void LinkedList::print() {
    ListNode* curr = head;
    while (curr != NULL) {//遍历整个链表,遍历的过程中顺便打印data的值
        cout << curr->data;
        curr = curr->next;
        if (curr) {
            cout << " ";
        }
        else {
            cout << endl;
        }
    }
}

eleType LinkedList::sum() {
    ListNode* curr = head;
    eleType ret = 0;
    while (curr != NULL) {
        ret += curr->data;
        curr = curr->next;
    }
    return ret;
}

void LinkedList::append(eleType v) {
    insert(size, v);
}

void LinkedList::ascInsert(eleType value) {
    if (size == 0) {
        insert(0, value);
        return;
    }
    ListNode* curr = head;
    for (int i = 0; i < size; ++i) {
        if (value <= curr ->data) {
            insert(i, value);
            return;
        }
        curr = curr->next;
    }
    insert(size, value);
}
//主函数
int main() {
    int n, x;
    while (cin >> n >> x) {
        if (!n && !x) {
            break;
        }
        LinkedList l;
        while (n--) {
            int v;
            cin >> v;
            l.append(v);
        }
        l.ascInsert(x);
        l.print();
    }
    return 0;
}

4.1290. 二进制链表转整数 - 力扣(LeetCode)

/**

 * Definition for singly-linked list.

 * struct ListNode {

 *     int val;

 *     ListNode *next;

 *     ListNode() : val(0), next(nullptr) {}

 *     ListNode(int x) : val(x), next(nullptr) {}

 *     ListNode(int x, ListNode *next) : val(x), next(next) {}

 * };

 */

class Solution {

public:

    int getDecimalValue(ListNode* head) {

        int sum = 0;

        while(head){

            //sum * 2 等同于将当前的 sum 值左移一位(在二进制里,左移一位相当于乘以 2)。head->val 表示当前节点的值,该值要么是 0,要么是 1。

            sum = sum * 2+head->val;

            head = head->next;

        }

        return sum;

    }

};

5.面试题 02.02. 返回倒数第 k 个节点 - 力扣(LeetCode)

/**

 * Definition for singly-linked list.

 * struct ListNode {

 *     int val;

 *     ListNode *next;

 *     ListNode() : val(0), next(nullptr) {}

 *     ListNode(int x) : val(x), next(nullptr) {}

 *     ListNode(int x, ListNode *next) : val(x), next(next) {}

 * };

 */

class Solution {

public:

    int kthToLast(ListNode* head, int k) {

        ListNode *fast =head;

        while(k--){

            fast = fast->next;

        }

        //fast先走k步,然后一起走,fast为空则slow到位

        ListNode *slow = head;

        while(fast){

            fast = fast->next;

            slow = slow->next;

        }

        return slow->val;

    }

};

6.LCR 140. 训练计划 II - 力扣(LeetCode)

/**

 * Definition for singly-linked list.

 * struct ListNode {

 *     int val;

 *     ListNode *next;

 *     ListNode() : val(0), next(nullptr) {}

 *     ListNode(int x) : val(x), next(nullptr) {}

 *     ListNode(int x, ListNode *next) : val(x), next(next) {}

 * };

 */

class Solution {

public:

    ListNode* trainingPlan(ListNode* head, int cnt) {

        ListNode *fast = head;

        while(cnt--){

            fast = fast->next;

        }

        ListNode *slow = head;

        while(fast){

            fast = fast->next;

            slow = slow->next;

        }

        return slow;

    }

};

7.876. 链表的中间结点 - 力扣(LeetCode)

/**

 * Definition for singly-linked list.

 * struct ListNode {

 *     int val;

 *     ListNode *next;

 *     ListNode() : val(0), next(nullptr) {}

 *     ListNode(int x) : val(x), next(nullptr) {}

 *     ListNode(int x, ListNode *next) : val(x), next(next) {}

 * };

 */

class Solution {

public:

    ListNode* middleNode(ListNode* head) {

        ListNode *fast = head;

        ListNode *slow = head;

        while(fast){

            fast = fast->next;

            if(fast == NULL){

                return slow;

            }

            fast = fast->next;

            if(fast == NULL){

                return slow->next;

            }

            slow = slow->next;

        }

        return slow;

    }

};

8.面试题 02.03. 删除中间节点 - 力扣(LeetCode)

/**

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

        node ->next= node->next->next;

    }

};

你可能感兴趣的:(算法,数据结构)