今天我们来聊聊数组跟链表,是非常基础的数据结构。
数组:
数组是无序的元素序列。
示例如下:
int[] arr = {10, 20, 30, 40, 50}
数组的特点是:元素地址是连续的,随机访问速度快。
链表(linked list):
链表(linked list)是由一组被称为结点的数据元素组成的数据结构,每个结点都包含结点本身的信息和指向下一个结点的地址。由于每个结点都包含了可以链接起来的地址信息,所以用一个变量就能够访问整个结点序列。也就是说,结点包含两部分信息:一部分用于存储数据元素的值,称为信息域;另一部分用于存储下一个数据元素地址的指针,称为指针域。
链表分为 【单向链表】 和 【双向链表】。
单向链表:(图片来源于网络)
删除:
(删除 “节点30”)(可以对比数组等也可以加上题目)
删除之前:“节点20” 的后继节点是 “节点30”,而 “节点30”的后继节点是 “节点40”
删除之后:“节点20” 的后继节点是 “节点40”
增加:
(增加 “节点25”)
增加之前:“节点20” 的后继节点是 “节点30”
增加之后:“节点20” 的后继节点是 “节点25”,“节点25” 的后继节点是 “节点30”
python 实现:
class Node:
def __init__(self, data=None, next=None):
self.data = data
self.next = next
def set_data(self, data):
self.data = data
def get_data(self):
return self.data
def set_next(self, next):
self.next = next
def get_next(self):
return self.next
class SinglyLinkedList:
def __init__(self):
self.head = None
self.size = 0
def add(self, value):
"""
Add element to list
Time Complexity: O(N)
"""
node = Node(value)
node.set_next(self.head)
self.head = node
self.size += 1
def _search_node(self, value, remove=False):
current = self.head
previous = None
while current:
if current.data == value:
break
else:
previous = current
current = current.next
if remove and current:
if previous is None: # Head node
self.head = current.next
else: # None head node
previous.set_next(current.next)
self.size -= 1
return current is not None
def remove(self, value):
"""
Remove element from list
Time Complexity: O(N)
"""
return self._search_node(value, True)
def search(self, value):
"""
Search for value in list
Time Complexity: O(N)
"""
return self._search_node(value)
def size(self):
"""
Return size of list
"""
return self.size
双向链表:
它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
至于 【删除】 和 【添加】的操作,跟 【单向链表】相似。
链表跟数组的区别:
所以链表存在的问题:
在需要读取链表的最后一个元素时,你不能直接读取,因为你不知道它所处的地址,必须先访问元素#1,从中获取元素#2的地址,再访问元素#2并从中获取元素#3的地址,以此类推,直到访问最后一个元素。需要同时读取所有元素时,链表的效率很高:你读取第一个元素,根据其中的地址再读取第二个元素,以此类推。但如果你需要跳跃,链表的效率真的很低。
参考链接:
(1) http://www.cnblogs.com/skywang12345/p/3561803.html(非常不错的博客)
题目:面试题3:二维数组中的查找(剑指offer)
题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有改整数。
当我们需要解决一个复杂的问题时,一个很有效的办法就是从一个具体的问题入手,通过分析简单具体的例子,试图寻找普遍的规律。
bool Find(int* matrix, int rows, int columns, int number)
{
bool found = false;
if (matrix != NULL && rows > 0 && columns > 0)
{
int row = 0;
int column = column - 1;
while (row < rows && column >= 0)
{
if (matrix[row * column + column] == number)
{
found = true;
break;
}
else if (matrix[row * columns + column] > number)
--column;
else:
++row;
}
}
return found
}
python 版本
# -*- coding:utf-8 -*-
class Solution:
# array 二维列表
def Find(self, target, array):
# write code here
row=len(array)
col=len(array[0])
if row > 0 and col > 0:
i = 0
j = col -1
while i < row and j >= 0:
if array[i][j] == target:
return True
elif array[i][j] > target:
j = j - 1
else:
i = i + 1
return False
关键点:考察应聘者分析问题的能力。当应聘者发现问题比较复杂时,能不能通过具体的例子找出其中的规律,是能否解决这个问题的关键所在。这个题目只要从一个具体的二维数组的右上角开始分析,就能找到查找的规律,从而找到解决问题的突破口。
关于链表的题目:
题目描述
输入一个链表,从尾到头打印链表每个节点的值。(剑指offer)
python 代码实现
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回从尾部到头部的列表值序列,例如[1,2,3]
def printListFromTailToHead(self, listNode):
# write code here
l = []
head = listNode
while head:
l.insert(0, head.val)
head = head.next
return l