【LeetCode】Sama的个人记录_5

 

 

▊【Q22】(md) 括号生成
   数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

 
示例:
输入
   n = 3
输出:[
   “((()))”,
   “(()())”,
   “(())()”,
   “()(())”,
   “()()()”
   ]

class Solution {
	/*
	* 【回溯算法】
	* 思路 :其实这是很典型的需要减枝的回溯算法,应该不难想到
	* 
	* 这类回溯算法与递归回溯不同,逻辑优美巧妙且简单;下面简单说一下回溯方法 traceBack的参数 :
	* 
	* int n 是每一层都需要的信息(要用于判断回溯的终止(回头)条件)
	* String tempString 暂存串,不必多说
	* int L, int R 是用于减枝的(右括号不可能多于左括号)
	*/
    public List<String> generateParenthesis(int n) {
    	traceBack(n, "", 0, 0);
    	return resList;	
    }
    
    public List<String> resList = new ArrayList<>();
    
    public void traceBack(int n, String tempString, int L, int R) {
    	if(R + L == 2*n) {
    		if( R == n && L == n) {
    			resList.add(tempString.toString());
    			return;
    		}else {
    			return;// 减枝
    		}
    	}
    	if(L < R) {
    		return;// 减枝
    	}
    	traceBack(n, tempString + "(", L+1, R);
    	traceBack(n, tempString + ")", L, R+1);
    }
}

 

 

▊【Q26】(ez) 删除数组的中的重复项
 
给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
 
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

 
示例 1:

给定数组 nums = [1,1,2],

函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。

你不需要考虑数组中超出新长度后面的元素。
 
示例 2:

给定 nums = [0,0,1,1,1,2,2,3,3,4],

函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。

你不需要考虑数组中超出新长度后面的元素。

class Solution {
    public int removeDuplicates(int[] nums) {
    	/*
    	* 覆盖的思想,很简单
    	* 题目说了很多,其实就是在引导与暗示我们使用覆盖的思想
    	*/
    	if(nums == null || nums.length == 0)		return 0;
    	
    	int len = 0;
    	for(int i = 0 ; i < nums.length ; i++) {
    		if( i > 0 && nums[i] == nums[i-1]) {	
    			continue;
    		}else {
    			nums[len++] = nums[i];
    		}
    	}
    	return len;
    }
}
class Solution {
    public int removeDuplicates(int[] nums) {
    	/*
    	* 通过现象看本质,我们随手写出的代码,其实利用了一个经典的算法思想:
    	* 【双指针】
    	* 在上面那段代码中,len是一个"慢指针",i是"快指针",它们从同一侧开始同向移动
    	* 
    	* 把它们分别换成 i, j后,双指针思想便显而易见了:
    	*/
    	if(nums == null || nums.length == 0)		return 0;
    	
    	int i = 0;
    	int j = 0;
    	for( ; j < nums.length ; j++) {
    		if( j > 0 && nums[j] == nums[j-1]) {	
    			continue;
    		}else {
    			nums[i++] = nums[j];
    		}
    	}
    	return i;
    }
}

 

 

 

预警 !

Warning !

KMP算法预警 ! ! !

▊【Q28】(hd) 实现 strStr(即indexOf)
 
实现 strStr() 函数。
 
   给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置(从0开始)。如果不存在,则返回 -1。
 
示例 1:

   输入: haystack = “hello”, needle = “ll”
   输出: 2
 
示例 2:

   输入: haystack = “aaaaa”, needle = “bba”
   输出: -1
 
说明:

   当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

   对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。

class Solution {
    public int strStr(String haystack, String needle) {
    	/*
    	* 【KMP算法】
    	* 简单说一下我浅薄的理解吧!
    	* 		KMP算法用于字符串的匹配
    	* 		该算法分为两部分,但两部分的核心精髓相同
    	* 			一是根据模式串,生成next数组(★★★)
    	* 			二是用模式串去匹配主串,在匹配失败时根据next数组进行回溯(回退),而不是直接退到模式串的0索引
    	* 
    	* 		这是典型的空间换时间
    	*/
    	if(needle == null || needle.length() == 0)	return 0;
    	
    	char[] t = haystack.toCharArray();
    	char[] p = needle.toCharArray();
    	int i = 0;		// 主串位置
    	int j = 0;		// 模式串位置
    	int[] next = getNext(needle);
    	while(i < t.length && j < p.length) {
    		if(j == -1 || t[i] == p[j]) {	//当j为-1时,要移动的是i,当然j也要归零
    			i++;						
    			j++;					// 相同则两串的指针都递增
    		}else {
    			j = next[j];		// 不同则j回到指定位置
    		}   			
    	}
    	if(j == p.length) {
    		return i - j;
    	}else {
    		return -1;
    	}
    }
    
    public static int[] getNext(String needle) {
    	char[] p = needle.toCharArray();
    	int[] next = new int[p.length];
    	next[0] = -1;
    	int j = 0;	// p数组的下标
    	int k = -1;	// 修正过的最大相同前后缀长度
    	while(j < p.length - 1) {
    		if(k == -1 || p[j] == p[k]) {
    			j++;
    			k++;
    			if(p[j] == p[k]) {		// 这里对next数组进行了优化
    				next[j] = next[k];	// 如果p[j + 1] == p[k + 1],回退后仍然失配,所以要继续回退
    			}else {
    				next[j] = k;
    			}
    		}else {
    			k = next[k];			// 回退
    		}
    	}
    	return next;
    }
    
    // 未优化的next数组
    public static int[] getNext2(String needle) {
    	char[] p = needle.toCharArray();
    	int[] next = new int[p.length];
    	next[0] = 0;
    	int j = 1;		// p数组的下标
    	int k = 0;		// 最大相同前后缀长度
    	for( ; j < p.length ; j++) {
    		while(k > 0 && p[j] != p[k])	k = next[k - 1];  // 回退
    		if(p[j] == p[k])  k++;
    		next[j] = k;
    	}
    	return next;
    }
}

 

 

 

 

 

 

 

 

 

 

Qs from https://leetcode-cn.com
♥ loli suki
♠ end

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值