1.请回答Arrry&List,数组和链表的区别。
数组的特点:
数组是将元素在内存中连续存放,由于每个元素占用的内存相同,可以通过下表迅速访问数组中的任意元素。数组的插入和删除数据效率低,插入数据时,这个位置后面的数据都要逐一往后移动;删除数据时,这个位置后面的数据也要逐一往前移动。但是数组的随机读取效率很高,因为数组是连续的,知道每一个数据的内存地址,可以直接找到地址的数据。如果应用需要快速访问数据,很少或不插入和删除元素,就应该用数组。数组需要预留空间,在使用前要先申请内存空间的大小,因此有可能会浪费内存空间。而且数组不利于扩展,数组定义的空间不足时需要寻找新的大空间,重新定义数组。
链表的特点:
链表中的元素在内存中不是顺序存放的,而是通过存在在元素中的指针联系到一起。比如,上一个元素有个指针知道下一个元素,一次类推,知道最后一个元素。如果要访问链表中的一个元素,就需要从第一个元素开始,一直找到需要的元素位置。但是增加和删除一个元素对于链表数据结构就非常简单了,只需要修改元素中的指针就可以了。如果应用需要经常插入和删除元素的话就需要用链表数据结构了。不用指定大小,扩展方便。而且链表大小无需定义,数据随意增删。
数组优点:
随机访问性强;查找速度快;
数组缺点:
插入和删除效率低;可能浪费内存;内存空间要求高,必须有足够的连续内存空间;数组大小固定,不能动态扩展。
链表优点:
插入和删除速度快;内存利用率高,不会浪费内存;大小没有固定,扩展非常灵活
链表缺点:
不能随机查找,必须从第一个开始遍历,查找效率低。
● 一个长度为n的整形数组,数组中每个元素的取值范围是[0,n-1],判断该数组否有重复的数,请说一下你的思路并手写代码
把每个数放在自己对应的序号上,如果某个位置上有和自己对应序号相同的数,那么就是有重复的数值。时间复杂度为O(n),同时为了节省空间复杂度,可以在原数组上进行操作,空间复杂度为O(1)
bool IsDuplicateNumber(int *array, int n)
{
if(array==NULL) return false;
int i,temp;
for(i=0;i<n;i++)
{
while(array[i]!=i)
{
if(array[array[i]]==array[i])
return true;
temp=array[array[i]];
array[array[i]]=array[i];
array[i]=temp;
}
}
return false;
}
● 请你手写代码,如何合并两个有序链表
方法一:归并,逐一将两条链表合并到新的链表中
方法二:递归
class Solution{
public:
ListNode* mergeTwoLists(ListNode* l1,ListNode* l2)
{
if(l1==NULL) return l2;
if(l2==NULL) return l1;
if(l1->val <l2->val)
{
l1->next = mergeTwoLists(l1->next,l2;
return l1;
}
else
{
l2->next = mergeTwoLists(l1,l2->next);
return l2;
}
}
}
● 手写代码:反转链表
方式一:迭代,逐次将原链表的第一个结点取出然后用头插法插入到新链表中。
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* newList = NULL;
ListNode* p = head;
ListNode* next = NULL;
while(p!=NULL)
{
next = p->next;
p->next = newList;
newList = p;
p = next;
}
return newList;
}
};
方式二:递归,
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==NULL||head->next==NULL) return head;
ListNode* newList = reverseList(head->next);
head->next->next=head;
head->next=NULL;
return newList;
}
};