在平常的应用场景中很多时候需要将繁杂的信息进行融合,比如零散的时间戳信息进行合并,顺序链表的合并就完美的解决这种问题的痛点。相对于原本的直接合并然后再进行排序,数据结构的复杂度不一样,因此就有类似此题的北京。融合有序链表没必要使用这么大的复杂度。
解决代码如下:
/*** 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* mergeTwoLists(ListNode* list1, ListNode* list2) {ListNode dummy(0); // 创建一个虚拟头结点ListNode* current = &dummy; // 用于遍历合并后的链表while (list1 && list2) { //两个都不空if (list1->val < list2->val) {current->next = list1;list1 = list1->next;} else {current->next = list2;list2 = list2->next;}current = current->next;//下一个节点变量出来}if (list1) { //list1这时候非空,说明还剩下,还剩下就接在后面current->next = list1;} else { //否则就是list2非空,还剩下,还剩家就接在后面current->next = list2;}return dummy.next; // 返回合并后的链表的头结点}
};
链表的属性技巧的使用:创建虚拟头节点。ListNode dummy(0); // 创建一个虚拟头结点将 链表的val值设置为0,链表的next设置为NULL。
list慢慢向下滑动,只要小于的都留下,共同有部分慢慢往后滑动排序拿到,然后把非空字符串的next接在后面剩下的非空字符串。
struct结构体的初始化技巧,与C++有什么区别。
在C++中,结构体(struct)和类(class)之间的主要区别可以简要描述如下:
-
默认访问权限:
- 结构体的成员默认为公共(public)访问权限,意味着它们可以在结构体外部访问。
- 类的成员默认为私有(private)访问权限,意味着它们不能在类外部直接访问。
-
数据成员和方法:
- 结构体通常用于表示数据结构,其成员变量(字段)通常是数据。
- 类通常用于建模对象,其成员变量可以包括数据和方法(成员函数)。
-
继承:
- 类支持继承,允许创建派生类。
- 结构体通常不用于创建派生结构。
-
面向对象特性:
- 类通常更适合实现面向对象编程的特性,如封装、继承和多态。
- 结构体通常用于简单的数据存储和传递。
类的作用比起结构体
因为类提供了更多的面向对象编程特性,如封装、继承和多态,以及更强大的成员函数和访问权限控制。
关于封装、继承、多态(面试常用)
封装
概念:隐藏对象的属性和实现细节,仅对外公开接口和对象进行交互。
函数也是封装的一种形式,函数所执行的细节行为被封装在函数实体中,同时隐藏了实现细节(即你可以调用一个函数,但是不能够访问函数所执行的语句)
封装的意义
1.可将属性和行为放在一起去表示一个事物
2.将属性和行为加以权限控制
访问权限:
1.public
2.protected
3.private
注意struct中的数据默认公共,class默认权限私有这是去呗
关于继承(可以基于某些共同属性)
我们称已存在的用来派生新类的类为基类,又称为父类。由已存在的类派生出的新类称为派生类,又称为子类。
基类负责定义所有类共同拥有的成员,而每个派生类定义各自特有的成员。
派生类必须通过使用类派生列表明确指出它是从哪个类继承而来,并说明它是公有继承,保护继承还是私有继承。
下面是继承可以完成的一些操作:
可以再已有类的基础上添加功能。
可以给类添加数据。比如说基类马,可以派生一个白马类,在内加入颜色属性:白色
可以修改类方法的行为。
当然,以上都可以通过复制修改源代码来完成,但继承机制只需要提供新特性,甚至只看对外接口不用看源码就可以派生出类,添加新特性。
关于多态
多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。
C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。
下面的实例中,基类 Shape 被派生为两个类,如下所示。
#include <iostream>
using namespace std;class Shape {protected:int width, height;public:Shape( int a=0, int b=0){width = a;height = b;}int area(){cout << "Parent class area :" <<endl;return 0;}
};
class Rectangle: public Shape{public:Rectangle( int a=0, int b=0):Shape(a, b) { }int area (){ cout << "Rectangle class area :" <<endl;return (width * height); }
};
class Triangle: public Shape{public:Triangle( int a=0, int b=0):Shape(a, b) { }int area (){ cout << "Triangle class area :" <<endl;return (width * height / 2); }
};
// 程序的主函数
int main( )
{Shape *shape;Rectangle rec(10,7);Triangle tri(10,5);// 存储矩形的地址shape = &rec;// 调用矩形的求面积函数 areashape->area();// 存储三角形的地址shape = &tri;// 调用三角形的求面积函数 areashape->area();return 0;
}
导致错误输出的原因是,调用函数 area() 被编译器设置为基类中的版本,这就是所谓的静态多态,或静态链接 - 函数调用在程序执行前就准备好了。有时候这也被称为早绑定,因为 area() 函数在程序编译期间就已经设置好了。
但现在,让我们对程序稍作修改,在 Shape 类中,area() 的声明前放置关键字 virtual,如下所示:
此时,编译器看的是指针的内容,而不是它的类型。因此,由于 tri 和 rec 类的对象的地址存储在 *shape 中,所以会调用各自的 area() 函数。
正如您所看到的,每个子类都有一个函数 area() 的独立实现。这就是多态的一般使用方式。有了多态,您可以有多个不同的类,都带有同一个名称但具有不同实现的函数,函数的参数甚至可以是相同的
虚函数
虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。
我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。
您可能想要在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。
我们可以把基类中的虚函数 area() 改写如下:
解决的痛点
1. 基类指针,指向派生类的时候,同样的基类指针指向派生类的属性的时候,派生类得新定义作为优先选项
2. virtual 虚函数与纯虚函数,基类不定义就使用纯虚函数,基类定义了就是虚函数。前缀增加virtual
virtual int area() = 0;
//虚类进行操作的area(),后面分号之前=0就可以了,基类只有名称没有功能。