【R&A】extracts & reverse-linked-list

摘录

我们曾提出心理学研究的主要目标之一是发现人类不同行为产生的原因,其中解释的一个重要维度便是遗传与环境。是致力于改变某种社会环境,还是设法改变人的特质,这就需要分辨出遗传与环境因素在其中所起的作用。

由于脑增大,我们的祖先就变得聪明起来,能够发展复杂的思维、推理、记忆和筹划能力(但是体积更大的脑并不能保证人类变得更聪明,重要的是脑内发展和扩展功能档次高的组织)。语言功能可以使人们彼此共享经验,吸取教训,而不必非得亲身通过尝试与错误。交谈甚至诙谐的玩笑,可以增强自然群居成员间的联系。更重要的是,语言使人类积累的文明和精神财富可一代代地传递下去。

请记住,基因密码没有特殊指向性,正如一个人个子高,未必就是一个好的篮球手一样。基因型的表达还需要环境条件的呼应。例如,一个人的身体是否高大,既决定于遗传因素,也取决于营养条件。无论男性还是女性个体,都可以通过特殊锻炼程序,使身体变得强壮。智力增长也取决于遗传潜力和教育经历。基因或环境都不能单独决定你是谁或你会变成哪类人。

人类在进化之前是群居的,分成不少小的群体,群内成员彼此很熟悉;可现代人大多生活在城市环境里,每个人周围大多是陌生人。我们不再结合成十分紧密的群体,共享一定的空间。原来这种紧密结合的种群部落有利于克服自然灾害,彼此依靠体验到安全与幸福的生活。我们能做什么?虽然不能逆文化发展的潮流,却可以通过你与家里人和朋友更紧密联系以产生类似的效果。

反转链表

  • 方法:双指针法之前后指针
  • 过程:
反转链表
  • 思路:如果链表节点小于两个,就直接返回;特殊处理:把第二个节点指向头节点,把头节点指向空,这样做之后第二、三节点的地址会丢失,所以要先存储起来;后续节点的操作:将after节点指向before节点,然后before和after都往后移动一位,注意事先保存会丢失的地址
  • 代码
#include <bits/stdc++.h>  // 万用头
using namespace std;
struct ListNode {
    int val;
    ListNode* next;
    // 自定义构造函数
    ListNode(int val1, ListNode* next1 = nullptr) {
        val = val1;
        next = next1;
    }
};
ListNode *reverseList(ListNode *head) {
    // 如果链表节点小于两个,就直接返回
    if(head == nullptr || head->next == nullptr) {
        return head;
    }
    // 特殊处理:把第二个节点指向头节点,把头节点指向空;这样做之后第二、三节点的地址会丢失,所以要先存储起来
    ListNode *before = head->next;
    ListNode *after = head->next->next;
    head->next->next = head;
    head->next = nullptr;
    // 后续节点的操作:将after节点指向before节点,然后before和after都往后移动一位,注意事先保存会丢失的地址
    while(after != nullptr) {
        ListNode *ptr = before;
        ListNode *tmp = after->next;
        before = after;
        after->next = ptr;
        after = tmp;
    }
    return before;
}
int main() {
    // 根据数组创建链表,需要反向遍历
    vector<int> nums = {1,2,3,4};
    ListNode* head1 = nullptr;
    for (vector<int>::reverse_iterator it = nums.rbegin(); it != nums.rend(); it++) {
        head1 = new ListNode(*it, head1);
    }
    ListNode* ptr = reverseList(head1);
    // 遍历链表
    cout<< "[ ";
    while (ptr != nullptr) {
        cout << ptr->val << " ";  // Process node
        ptr = ptr->next;          // Move to next node
    }
    cout<< "]";
    return 0;
}

  • 特殊情况分析:数字长度为0、1、2 正常
  • 优化:其实只要给before一个初始值NULL,就可以合并情况,简化操作了
ListNode* reverseList(ListNode* head) {
    ListNode* temp; // 保存cur的下一个节点
    ListNode* after = head;
    ListNode* before = NULL;
    while(after) {
        temp = after->next;  // 保存一下 after的下一个节点,因为接下来要改变after->next
        after->next = before; // 翻转操作
        // 更新before 和 after指针
        before = after;
        after = temp;
    }
    return before;
}
  • 时间复杂度:O(n)

  • 空间复杂度:O(1)

  • 方法:递归

  • 代码:

ListNode* reverse(ListNode* before,ListNode* after){
    if(after == NULL) return before;
    ListNode* temp = after->next;
    after->next = before;
    // 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步
    // before = after;
    // after = temp;
    return reverse(after,temp);
}
ListNode* reverseList(ListNode* head) {
    // 和双指针法初始化是一样的逻辑
    // ListNode* after = head;
    // ListNode* before = NULL;
    return reverse(NULL, head);
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容