self-summary-2020-02-04
数组
数组是一个线性表,存储相同数据结构的连续的内存空间。
数组的优劣
- 优势
-
随机访问时间复杂度为常数级别。
- 支持cpu缓存,访问速度更加快速。(因为内存空间是连续的所以知道收地址的内存地址,cpu缓存就可以预读整个数组的所有数据。)
- 一维数组的内存计算公式:a[i]address = base_address + (i-1)*data_type_size
- 二维数组的内存计算公式: address = base_address + ( i * n + j) * type_size
-
- 劣势
- 删除慢
- 删除一个数据需要进行数据搬移,是非常耗时的
- 优化
- 对删除的数据进行标记,不删除,当数组的存储空间不足的时候,在进行一次整体的删除操作,减少了搬移的次数(垃圾回收机制的标记清楚算法)
- 插入慢
- 插入数据的时候,数据搬移
- 优化
- 针对有序数组没发优化
- 无序数组
- 插入的新数据都插入末尾
- 跟要插入的数据进行交换。
- 大小有限,警惕数组索引越界(java.lang.ArrayIndexOutOfBoundsException)
- 删除慢
- 容器与数组的对比
- 优势
- 容器最大的优势就是1将数组的操作细节封装了起来。2.支持动态扩容。
- 劣势
- 容器不能存储基本数据类型
- 数组效率高(知道数据大小的情况下)(底层开发数组的效率更高)
- 多维情况下,数组更加直观
- 优势
leetcode题目(移动零):
class Solution {
//first solution
//1.just find non-zero data 2.finally fill of all zero data.3.index is non-zero data's count.
public void moveZeroes(int[] nums) {
int index = 0;
for(int num:nums){
if(num!=0){
nums[index++]=num;
}
}
while(index<nums.length){
nums[index++] = 0;
}
}
//second solution
//1.tow pointer ,first pointer is the first zero data's address,second pointer is the foreach count.
public void moveZeroesSecond(int[] nums){
//first pointer
int i = 0;
//second pointer
int j = 0;
for(; j< nums.length; j++){
//if nums[j] != 0 i++
if( nums[j] != 0 ) {
// exchage condition
if( i != j){
exchage(i,j,nums);
}
i++;
}
}
}
private void exchange(int[] nums, int i, int j) {
nums[i] = nums[i] ^ nums[j];
nums[j] = nums[i] ^ nums[j];
nums[i] = nums[i] ^ nums[j];
}
}
链表
链表的分类:
- 单向链表
- 双向链表
- 循环链表
- 静态链表
链表的优劣:
- 优势
- 删除,插入快
- 劣势
- 随机访问慢
- 频繁的删除插入容易产生内存碎片,造成频繁的gc
链表实战
1.链表环形检测(leetcode):
//给定一个链表,判断链表中是否有环。
//
// 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
//
//
//
// 示例 1:
//
// 输入:head = [3,2,0,-4], pos = 1
//输出:true
//解释:链表中有一个环,其尾部连接到第二个节点。
//
//
//
//
// 示例 2:
//
// 输入:head = [1,2], pos = 0
//输出:true
//解释:链表中有一个环,其尾部连接到第一个节点。
//
//
//
//
// 示例 3:
//
// 输入:head = [1], pos = -1
//输出:false
//解释:链表中没有环。
//
//
//
//
//
//
// 进阶:
//
// 你能用 O(1)(即,常量)内存解决此问题吗?
// Related Topics 链表 双指针
//leetcode submit region begin(Prohibit modification and deletion)
//leetcode submit region end(Prohibit modification and deletion)
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
public class Solution {
// 1.fast pointer and slow pointer ,fast's start is one,every time two steps, slow's statr is zero , every time one step. if the fast catch catch up the slow,this list is cycle,else is no cycle.
public boolean hasCycle(ListNode head) {
if(head == null){
return false;
}
ListNode slow = head;
ListNode fast = head.next;
while(fast == null && fast.next == null){
slow = slow.next;
fast = fast.next.next;
if(fast == slow){
return true;
}
}
return false;
}
}
2.单链表反转
/**
* merge sorted list
* @param l1
* @param l2
* @return
*/
public LinkedList mergeTwoLists(LinkedList l1, LinkedList l2) {
LinkedList solider = new LinkedList(0);
LinkedList p = solider;
while(l1 != null && l2 != null) {
if(l1.value <= l2.value) {
p.next = l1;
l1 = l1.next;
}else{
p.next = l2;
l2 = l2.next;
}
p = p.next;
}
if(l1 == null) {
p.next = l2;
}
if(l2 == null) {
p.next = l1;
}
return solider.next;
}
3.两个有序的链表合并
/**
* merge sorted list
* @param l1
* @param l2
* @return
*/
public LinkedList mergeTwoLists(LinkedList l1, LinkedList l2) {
LinkedList solider = new LinkedList(0);
LinkedList p = solider;
while(l1 != null && l2 != null) {
if(l1.value <= l2.value) {
p.next = l1;
l1 = l1.next;
}else{
p.next = l2;
l2 = l2.next;
}
p = p.next;
}
if(l1 == null) {
p.next = l2;
}
if(l2 == null) {
p.next = l1;
}
return solider.next;
}
4.删除链表倒数第 n 个结点
/**
* delete the last k node
* @param node
*/
public void deletedTheLastKNode(LinkedList node,int k){
LinkedList kNode = node;
LinkedList preKNode = node;
//node count.
int count = 1;
while(kNode != null){
kNode = kNode.next;
count++;
if( count > k){
preKNode = preKNode.next;
}
}
if(count == k){
node = node.next;
}
if(count > k){
preKNode.next = preKNode.next.next;
}
}
/**
*
* @param list
* @param k
* @return
*/
public static LinkedList deleteLastKth(LinkedList list, int k) {
LinkedList fast = list;
int i = 1;
while(fast !=null && i < k){
fast = fast.next;
i++;
}
if(fast == null) {
return list;
}
LinkedList pre = null;
LinkedList slow = list;
while(fast.next != null){
pre = slow;
slow = slow.next;
fast = fast.next;
}
if(pre == null){
list = list.next;
}else {
pre.next = pre.next.next;
}
return list;
}
5.求链表的中间结点
/**
* find list mid
* @param head
*/
private LinkedList findListMid(LinkedList head){
if(head == null) {
return null;
}
//fast pointer and slow pointer,if fast get the end slow's address is the mid's address.
LinkedList slow = head;
LinkedList fast = head;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}