剑指offer第二版和专项突击版有啥区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer第二版和专项突击版有啥区别相关的知识,希望对你有一定的参考价值。

参考技术A 剑指offer第二版和专项突击版区别在于内容和重点不同:
1、内容上《剑指offer第二版》内部的题目顺序是按照从易到难的顺序排列,便于初学者逐步提升。
2、《剑指offer专项突击版》的内容上则把题目分成了10个章节,分别涵盖了数组、链表、栈和队列、字符串、树、图、算法思想、位运算、数学问题和多线程与并发等算法类型。
3、《剑指offer第二版》在对所有题目进行讲解时,都会详细地介绍题目的背景、算法思路和代码实现等内容,讲解比较全面。
4、《剑指offer专项突击版》则更加注重突出每种算法的核心思想和特点,给读者更深刻的印象。

Leetcode训练剑指 Offer(专项突击)——双指针全刷

目录

分享Leetcode——剑指Offer专项突击版——双指针刷题
https://leetcode-cn.com/problem-list/e8X3pBZi/

剑指 Offer II 006. 排序数组中两个数字之和——简单

题目描述:

题解

方法一:数组已经排序了,直接首尾双指针;

class Solution 
    public int[] twoSum(int[] numbers, int target) 
        int arr[] = new int[2];
		int i = 0;
		int j = numbers.length-1;
		while(i<=j) 
			if (numbers[i]+numbers[j]>target) 
				j--;
			else if (numbers[i]+numbers[j]<target) 
				i++;
			else 
				arr[0]=i;
				arr[1]=j;
				break;
			
		
        return arr;
    


剑指 Offer II 007. 数组中和为 0 的三个数——中等

题目描述

题解:

方法一:暴力破解(超时)

题解链接:https://leetcode-cn.com/problems/1fGaJU/solution/jian-dan-yi-dong-javac-pythonjs-san-shu-nu6el/

class Solution 
    public List<List<Integer>> threeSum(int[] nums) 
    	if (nums==null||nums.length<3) 
			return new ArrayList<>(); 
		
    
    	Set<List<Integer>> res = new HashSet<>();
		Arrays.sort(nums);	// 时间复杂度 O(nlogn)
//    	Set<List<Integer>> set = new HashSet<>();
    	
		// O(n^3)
    	for (int i = 0; i < nums.length; i++) 
			for (int j = i+1; j < nums.length; j++) 
				for (int k = j+1; k < nums.length; k++) 
					if (nums[i]+nums[j]+nums[k]==0) 
//						List<Integer> temp = Arrays.asList(nums[i],nums[j],nums[k]);
//						Collections.sort(temp); 	// 对list排序
						res.add(Arrays.asList(nums[i],nums[j],nums[k]));
					
				
				
		
    	return new ArrayList<>(res);
    

方法二:双指针

题解链接:https://leetcode-cn.com/problems/1fGaJU/solution/jian-dan-yi-dong-javac-pythonjs-san-shu-nu6el/

class Solution 
	public List<List<Integer>> threeSum(int[] nums)
		if (nums==null||nums.length<3) 
			return new ArrayList<>(); 
		  	
		List<List<Integer>> res= new ArrayList<>();
		Arrays.sort(nums);  // 时间复杂度 O(nlogn)
		//时间复杂度  O(n^2)
		for (int i = 0; i < nums.length-2; i++) 	  // 时间复杂度O(n)
			// i 去重
			if (i>0 && nums[i]==nums[i-1]) 
				continue;
			
			// 在 i + 1 ... nums.length - 1 中查找相加等于 -nums[i] 的两个数
			int target = -nums[i];
			int left = i+1;
			int right = nums.length-1;
			while (left<right) 	// 时间复杂度O(n)
				int sum = nums[left]+nums[right];
				if (sum==target) 
					res.add(Arrays.asList(nums[i],nums[left],nums[right]));
					// 去重 如果前一个left==后面的left  跳过
//					while (left<right&& nums[left]==nums[++left]);
//					while (left<right&& nums[right]==nums[--right]);
					while (left<right) 
						left++;
						if (nums[left-1]!=nums[left]) 
							break;	// 当left-1 !=left 的时候 跳出left++循环 左指针去重完毕
						
					
					
					while (left<right) 
						right--;
						if (nums[right]!=nums[right+1]) 
							break;	// 当 right != right+1的时候 跳出right--循环 右指针去重完毕
						
					
				else if (sum < target) 
					left++;
				else 
					right--;
				
			
		
		return res;	// O(n)
	


剑指 Offer II 014. 字符串中的变位词——中等

题目描述

题解

class Solution 
    public boolean checkInclusion(String s1, String s2) 
    	int m = s1.length();
    	int n = s2.length();
    	if (m>n) 
			return false;
		
    	int cnt1[] = new int[26];
    	for (char c:s1.toCharArray()) 
    		cnt1[c - 'a']++;
		
    	int left = 0;
    	int cnt2[] = new int[26];
    	for(int right =0;right < n;right++) 
    		int idx = s2.charAt(right) - 'a';
    		cnt2[idx]++;
    		while (cnt2[idx]>cnt1[idx]) 
				cnt2[s2.charAt(left)-'a']--;
				left++;
			
    		if (right-left+1==m) 
				return true;
			
    	
    	return false;
    

优化

class Solution 
    public boolean checkInclusion(String s1, String s2) 
    	int n = s1.length();
    	int m = s2.length();
    	int cnt[] = new int[26];
    	for(int i=0;i<n;i++) 
    		cnt[s1.charAt(i)-'a']--;
    	
    	int left = 0;
    	for(int right=0;right<m;right++) 
    		int in = s2.charAt(right)-'a';
    		cnt[in]++;
    		while(cnt[in]>0) 
    			cnt[s2.charAt(left)-'a']--;
    			left++;
    		
    		if (right-left+1==n) 
				return true;
			
    	
    	return false;
    

复杂度分析


剑指 Offer II 018. 有效的回文——简单

题目描述

题解

方法一:无脑判断思维reverse()

class Solution 
    public boolean isPalindrome(String s) 
    	StringBuffer sb = new StringBuffer();
    	s = s.toLowerCase();
    	for (int i = 0; i < s.length(); i++) 
			char c = s.charAt(i);
			if (Character.isLetterOrDigit(c)) 
				sb.append(c);
			
		
    	return sb.toString().equals(new StringBuffer(sb).reverse().toString());
    

方法二:双指针

class Solution 
    public boolean isPalindrome(String s) 
    	int left = 0;
    	int right = s.length() - 1;
    	s = s.toLowerCase();
    	char c1;
    	char c2;
    	while (left < right) 
			if (!Character.isLetterOrDigit(s.charAt(left))) 
				left += 1;
			 else if (!Character.isLetterOrDigit(s.charAt(right))) 
				right -=1;
			 else 
				c1 = s.charAt(left);
				left++;
				c2 = s.charAt(right);
				right--;
				if (c1 != c2) 
					return false;
				
			
		
    	return true;
    


剑指 Offer II 019. 最多删除一个字符得到回文——简单

题目描述:

题解

class Solution 
    public boolean validPalindrome(String s) 
    	StringBuffer sb = new StringBuffer();
    	int left = 0;
    	int right = s.length()-1;
    	while (left<right) 
    		// 如果不相等,则分两种情况:删除左边的元素,或者右边的元素,再判断各自是否回文,满足一种即可。
			if (s.charAt(left)!=s.charAt(right)) 
				return isPalindrome(s, left+1, right)||isPalindrome(s, left, right-1);
			
			left++;
			right--;
		
    	return true;
    
    // 判断字符串 s 的 [left, right] 是否回文
    public boolean isPalindrome(String s, int left,int right) 
    	while (left<right) 
			if (s.charAt(left)!=s.charAt(right)) 
				return false;
			
			left++;
			right--;
		
    	return true;
    

复杂度分析


剑指 Offer II 021. 删除链表的倒数第 n 个结点——中等

题目描述

给定一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

示例 1:

题解

/**
 * Definition for singly-linked list.
 * public class ListNode 
 *     int val;
 *     ListNode next;
 *     ListNode() 
 *     ListNode(int val)  this.val = val; 
 *     ListNode(int val, ListNode next)  this.val = val; this.next = next; 
 * 
 */
class Solution 
    public ListNode removeNthFromEnd(ListNode head, int n) 
        // 创建辅助头节点,head , fast 和 slow 都指向这个辅助头节点
        ListNode fast =  new ListNode(0);
        fast.next = head;
        head = fast;
        ListNode slow = fast;

        // fast 指针先走 n + 1 个单位
        for(int i = 0; i <= n; i++)
            fast = fast.next;
        

        // fast 指针和 slow 指针一起移动,直到 fast 指向空后,slow 指针则指向倒数第 n + 1个节点。
        while (fast != null)
            slow = slow.next;
            fast = fast.next;
        
        
        // 删除倒数第 n 个节点
        slow.next = slow.next.next;

        // 由于我们设置了辅助头节点,所以 head.next 才是链表的首元节点。
        return head.next;
    

复杂度分析


剑指 Offer II 022. 链表中环的入口节点——中等

题目描述

示例 1:

示例 2:

示例 3:

题解

方法一:哈希表

一个非常直观的思路是:我们遍历链表中的每个节点,并将它记录下来;一旦遇到了此前遍历过的节点,就可以判定链表中存在环。借助哈希表可以很方便地实现。

public class Solution 
    public ListNode detectCycle(ListNode head) 
        ListNode pos = head;
        Set<ListNode> set = new HashSet<>();
        while (pos !=null) 
			if (set.contains(pos)) 
				return pos;
			 else 
				set.add(pos);
			
			pos = pos.next;
		 
        return pos;
    

复杂度分析

方法二:快慢指针