每日一道算法题+面试题day1-2

文章只是总结,便于面试和手写算法。细节和详细解释,请看:https://leetcode-cn.com/

1. 题目

算法题:
1. 反转链表:https://leetcode-cn.com/problems/reverse-linked-list/
2. 两两交换链表中的节点:https://leetcode-cn.com/problems/swap-nodes-in-pairs/
3. 判断链表是否有环:https://leetcode-cn.com/problems/linked-list-cycle/
4. K 个一组翻转链表:https://leetcode-cn.com/problems/reverse-nodes-in-k-group/
面试题:
1. Set是如何保证里面的元素唯一
2. 以登录界面为例子,设计MVP架构

2. 基本知识

2.1 数组

内存中的连续存储空间。

  • 查询时间复杂度:O(1)
  • 插入、删除时间复杂度:O(n)

2.3 链表

内存中非连续、非顺序的存储结构,数据原生的顺序通过链表中的指针链接次序实现。有单链表和双链表。适用于频繁插入删除,查询次数不多的场景。

  • 查询:O(n)
  • 插入、删除:O(1)

3. 算法题解题

3.1 反转链表

假设存在链表 1 → 2 → 3 → Ø,我们想要把它改成 Ø ← 1 ← 2 ← 3。把每个节点的next指向它的前一个节点即可。

该题解,时间复杂度O(n),空间复杂度O(1)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
public ListNode reverseList(ListNode head) {
    ListNode pre = null;
		
		ListNode cur = head;
		
		while(cur != null){
			
			ListNode nextTemp = cur.next;
			
			cur.next = pre;
			
			pre = cur;
			
			cur = nextTemp;
		}
		
		return pre;
	}
}

3.2 两两交换链表中的节点

递归解法:最小递归单元中,next链接head,然后前面换好的节点连接上next。

该题解时间复杂度O(n),空间复杂度O(1)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode swapPairs(ListNode head) {
        if(head == null || head.next == null)
		{
			return head;
		}
		
		ListNode next = head.next;
		head.next = swapPairs(next.next);
		next.next = head;
		return next;  
    }
}

3.3 判断链表是否有环

1->2->3->4和1->2->3->1->2的区别

第一种解法:使用一个set来存储ListNode节点,每次拿到当前节点,去set中查询是否重复,如果有,则重复

该解法时间复杂度O(n) 空间复杂度O(n)

public class Solution {
    public boolean hasCycle(ListNode head) {
        HashSet hashSet = new HashSet();
		while(head!= null){
			if (hashSet.contains(head)) {
				return true;
			}else{
				hashSet.add(head);
			}
			head = head.next;
		}
		return false;
    }
}

第二种解法:使用两个指针,一个快指针,一个慢指针,如果最后快慢指针相遇,则说明有环,否则无环

该解法时间复杂度为O(n) 空间复杂度为O(1)

public class Solution {
    public boolean hasCycle(ListNode head) {
        if (head == null || head.next == null) {
			return false;
		}
		
		ListNode slow = head.next;
		
		ListNode fast = head;
		
		while(slow != fast){
			if (slow == null || fast == null) {
				return false;
			}
			slow = slow.next;
			
			fast = fast.next.next;
		}
		
		return true;
    }
}

3.4 K个一组反转链表

示例 :
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5

解法:获取链表长度,除以k,得到有多少个需要翻转的子链表,子链表翻转完成后,拼接上之前剩余的链表即可

public ListNode reverseKGroup(ListNode head, int k) {
	if (head == null)
		return null;
	// 1.获得链表节点个数
	int count = 0;
	ListNode cur = head;
	while (cur != null) {
		count++;
		cur = cur.next;
	}

	// 2.获得需要翻转的组数
	int group = count / k;

	ListNode fakeHead = new ListNode(0), pre = fakeHead;
	cur = head;
	fakeHead.next = head;
	// 3.开始翻转
	while (group-- > 0) {
		// 3.1 组内翻转k-1次
		for (int i = 0; i < k - 1; i++) {
			ListNode tmp = cur.next;
			cur.next = tmp.next;
			tmp.next = pre.next;
			pre.next = tmp;
		}

		// 3.2 开始下一次翻转
		pre = cur;
		cur = cur.next;
	}
	return fakeHead.next;
}

4. 面试题解题

4.1 Set是如何保证里面的元素唯一

set保证里面元素的唯一性其实是靠两个方法,一是equals()和hashCode()方法

往set里面添加数据的时候一般会有隐式的操作

先是判断set集合中是否有与新添加数据的hashcode值一致的数据,

如果有,那么将再进行第二步调用equals方法再进行一次判断,

假如集合中没有与新添加数据hashcode值一致的数据,那么将不调用eqauls方法。

4.2 以登录界面为例子,设计MVP架构

明天补上,今天太晚了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值