leetCode解题报告5道题(九)
题目一:Combinations
Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.
For example,
If n = 4 and k = 2, a solution is:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
分析:
题意给我们一个数字n, 和一个数字k,让我们求出从 1~~n中取出k个数所能得到的组合数
所以这个题目给我们的第一感觉就是用递归是最方便的了,咱试试递归的方法哈。假设读者对递归方法有疑问,能够看看我之前总结的一个递归算法的集合。
AC代码:
public class Solution {
//终于结果
private ArrayList<ArrayList<Integer>> arrays = new ArrayList<ArrayList<Integer>>();
public ArrayList<ArrayList<Integer>> combine(int n, int k) {
//把组合设想成仅仅能升序的话,能做开头的数字仅仅有 1 ~ n-k+1
for (int i=1; i<=n-k+1; ++i){
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(i);
cal(list, i+1, n, k-1); //递归
}
return arrays;
}
public void cal(ArrayList<Integer> list, int start, int end, int k){
//k==0表示这次list组合满足条件了
if (k == 0){
//copy
ArrayList<Integer> result = new ArrayList<Integer>(list);
arrays.add(result);
}
//循环递归调用
for (int i=start; i<=end; ++i){
list.add(i);
cal(list, i+1, end, k-1);
list.remove(list.size()-1);
}
}
}
题目二:Search a 2D Matrix
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
- Integers in each row are sorted from left to right.
- The first integer of each row is greater than the last integer of the previous row.
For example,
Consider the following matrix:
[
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
Given target = 3, return true.
分析:这道题目是剑指Offer上的老题目咯,可是解题的思路挺巧妙。本来不想把这题写在博文里的,后来想想或许有些同学没看过剑指Offer, 后续由于这题而去看下这本挺不错的书哈,于是把这题写在博文里了。并附上剑指offer的下载地址(http://download.csdn.net/detail/u011133213/7268315),这题便不做具体介绍。
AC代码:(复杂度O(m+n))
public class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int m = matrix.length;
int n = matrix[0].length;
int row = 0;
int col = n - 1;
while (m > row && col >= 0){
if (target == matrix[row][col]){
return true;
}
if (target > matrix[row][col]){
row++;//往下一行搜索
}else if (target < matrix[row][col]){
col--;//往左一列搜索
}
}
return false;
}
}
题目三:Scramble String
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.
Below is one possible representation of s1 = "great":
great
/ \
gr eat
/ \ / \
g r e at
/ \
a t
To scramble the string, we may choose any non-leaf node and swap its two children.
For example, if we choose the node "gr" and swap its two children, it
produces a scrambled string "rgeat".
rgeat
/ \
rg eat
/ \ / \
r g e at
/ \
a t
We say that "rgeat" is a scrambled string of "great".
Similarly, if we continue to swap the children of nodes "eat" and "at",
it produces a scrambled string "rgtae".
rgtae
/ \
rg tae
/ \ / \
r g ta e
/ \
t a
We say that "rgtae" is a scrambled string of "great".
Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.
分析:
这道题目的题意相信大家应该都看得懂,仅仅是做起来的话有些蛋疼.
我一開始用暴力法TLE,之后用DP才干够的.
详细看代码:
暴力法TLE:
public class Solution {
public boolean isScramble(String s1, String s2) {
if (s1 == null || s2 == null)
return false;
if (s1.equals(s2))
return true;
int len1 = s1.length();
int len2 = s2.length();
if (len1 != len2)
return false;
int[] hash = new int[26];
for (int i=0; i<len1; ++i){
hash[s1.charAt(i) - 'a']++;
}
for (int i=0; i<len2; ++i){
hash[s2.charAt(i) - 'a']--;
}
for (int i=0; i<26; ++i){
if (hash[i] != 0)
return false;
}
for (int i=1; i<len1; ++i){
boolean flags1 = (isScramble(s1.substring(0,i), s2.substring(0,i)) && isScramble(s1.substring(i,len1), s2.substring(i,len2)));
boolean flags2 = (isScramble(s1.substring(0,i), s2.substring(len2-i,len2)) && isScramble(s1.substring(i,len1), s2.substring(0,len2-i)));
if (flags1 && flags2){
return true;
}
}
return false;
}
}
DP动态规划:
设数组flags[len][len][len]来存储每个状态信息.
如flags[i][j][k] 表示s1字符串的第i个位置開始的k个字符和s2字符串的第j个位置開始的k个字符 是否满足scramble string
满足:flags[i][j][k] == true
不满足: flags[i][j][k] == false
那么题目所要的终于结果的值事实上就相当于是flags[0][0][len]的值了
那么状态转移方程是什么呢?
归纳总结法
假设k==1:
flags[i][j][1] 就相当于 s1的第i个位置起,取1个字符。s2的第j个位置起,取1个字符。那假设要使Scramble String成立的话,那么就仅仅能是这两个字符相等了, s1.charAt(i) == s2.charAt(j)
因此 flags[i][j][1] = s1.charAt(i) == s2.charAt(j);
假设k==2:
flags[i][j][2] 就相当于 s1的第i个位置起,取2个字符。s2的第j个位置起,取2个字符。那假设要使Scramble String成立的话,那么情况有下面两种
一种是flags[i][j][1] && flags[i+1][j+1][1] (就是两个位置的字符都相等 S1="TM" S2="TM")
一种是flags[i][j+1][1] && flags[i+1][j][1] (两个位置的字符刚好对调位置 S1="TM" S2="MT")
假设k==n:
设个变量为x
flags[i][j][n] =( (flags[i][j][x] && flags[i+x][j+x][k-x]) [第一种情况]
|| (flags[i][j+k-x][x] && flags[i+x][j][k-x]) ); [另外一种情况]
AC代码:
public class Solution {
public boolean isScramble(String s1, String s2) {
if (s1 == null || s2 == null)
return false;
if (s1.equals(s2))
return true;
int len1 = s1.length();
int len2 = s2.length();
if (len1 != len2)
return false;
int len = len1;
boolean[][][] flags= new boolean[len+1][len+1][len+1];
for (int t=1; t<=len; ++t){
for (int i=0; i<=len-t; ++i){
for (int j=0; j<=len-t; ++j){
if (t == 1){
flags[i][j][t] = (s1.charAt(i) == s2.charAt(j));
}else{
for (int k=1; k<t; ++k){
if (flags[i][j][t] == true){
break;
}else{
if ((flags[i][j][k] && flags[i+k][j+k][t-k])
|| (flags[i][j+t-k][k] && flags[i+k][j][t-k])){
flags[i][j][t] = true;
}
}
}
}
}
}
}
return flags[0][0][len];
}
}
题目四:
Rotate List
Given a list, rotate the list to the right by k places, where k is non-negative.
For example:
Given 1->2->3->4->5->NULL and k = 2,
return 4->5->1->2->3->NULL.
分析:
题意要求我们依据所给出的k值,把从最后一个非空结点向前的k个结点移动到链表的开头,又一次组成一个新的链表之后返回。
这道题目有点像经典的面试题“仅仅遍历一次,怎样找到链表倒数的第K个结点”,採用的是两个指针不一样的起始位置,一个指针从head開始出发,还有一个指针先让它走K步,当第2个指针为Null的时候,则第一个指针所指向的就是倒数第K个的值。
同理:
这里我们用两个指针就能够方便地搞定这个题目了,可是须要注意的是,这道题目
假设K大于了链表长度,比方K=3,Len=2的话,假设K步我们还没走完就碰到了Null结点,那么再从head開始走剩下的。直到K==0;
AC代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode rotateRight(ListNode head, int n) {
ListNode firstNode = head;//新链表的第一个结点
ListNode kstepNode = head;//走了k步的指针
ListNode preFirstNode = new ListNode(-1);//新链表第一个结点的前一个结点
ListNode preKstepNode = new ListNode(-1);//k步指针的前一个结点 if (head == null || n == 0){
return head;
}
int k = n; //先走K步
while (k != 0){
//假设走到链表结束了k还不为0,那么再回到head头结点来继续
if (kstepNode == null){
kstepNode = head;
}
kstepNode = kstepNode.next;
k--;
}
//假设刚好走到链表结束,那么就不用再处理了,当前的链表就满足题意了
if (kstepNode == null){
return firstNode;
}
//处理两个结点同一时候走,知道第二个指针走到Null,则第一个指针是倒数第K个结点
while (kstepNode != null){
preFirstNode = firstNode;
firstNode = firstNode.next; preKstepNode = kstepNode;
kstepNode = kstepNode.next;
}
preKstepNode.next = head;
preFirstNode.next = null; return firstNode;
}
}
题目五:Partition List
Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.
You should preserve the original relative order of the nodes in each of the two partitions.
For example,
Given 1->4->3->2->5->2 and x = 3,
return 1->2->2->4->3->5.
分析:
妈蛋,英文题目看着就是蛋疼,看了好久才理解它的题意:
题目要求我们说给出一个X的值,你要把全部的 小于X的值的结点放在全部大于或等于X的值的前面,关键这里X又等于3,跟题目里面给出的链表中当中一个结点的值一样,迷惑了。
一旦题意明确了,剩下的就好办了,竟然这种话,那我们仅仅须要先找出第一个 “大于或等于X值”的结点,并记录下它的位置。
然后剩下的仅仅要遍历一次链表,把小于X的插入到它的前面,大于或等于X 不变位置(由于我们这里找到的是第一个“大于或等于X值”的结点)。
AC代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode partition(ListNode head, int x) {
ListNode firstNode = head;
ListNode preFirstNode = new ListNode(-1);
preFirstNode.next = firstNode;
ListNode tempNode = head;
ListNode pretempNode = new ListNode(-1);
pretempNode.next = tempNode;
ListNode preHead = new ListNode(-1);
preHead.next = head; int index = 0;
//find the first (>= x)'s node
while (firstNode != null){
if (firstNode.val >= x){
break;
}else{
preFirstNode = firstNode;
firstNode = firstNode.next;
index++;//记录位置
}
}
//假设第一个满足条件的结点是头结点
if (firstNode == head){
preHead = preFirstNode;
}
//取得当前下标,假设在第一个满足条件的结点之前则不处理
int p = 0;
while (tempNode != null){
if (tempNode != firstNode){
//值小于x,而且在第一个满足条件结点之后。
if (tempNode.val < x && p > index){
/*做移动*/
pretempNode.next = tempNode.next;
tempNode.next = preFirstNode.next;
preFirstNode.next = tempNode;
preFirstNode = tempNode;
tempNode = pretempNode.next;
index++;
p++;
continue;
}
}
pretempNode = tempNode;
tempNode = tempNode.next;
p++;
} return preHead.next; }
}
leetCode解题报告5道题(九)的更多相关文章
- leetCode解题报告5道题(六)
题目一: Longest Substring Without Repeating Characters Given a string, find the length of the longest s ...
- leetCode解题报告5道题(七)
题目一:Interleaving String Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2 ...
- leetCode解题报告5道题(十)
题目一:Valid Number Validate if a given string is numeric. Some examples: "0" => true &quo ...
- LeetCode解题报告:Linked List Cycle && Linked List Cycle II
LeetCode解题报告:Linked List Cycle && Linked List Cycle II 1题目 Linked List Cycle Given a linked ...
- leetcode解题报告(2):Remove Duplicates from Sorted ArrayII
描述 Follow up for "Remove Duplicates": What if duplicates are allowed at most twice? For ex ...
- LeetCode 解题报告索引
最近在准备找工作的算法题,刷刷LeetCode,以下是我的解题报告索引,每一题几乎都有详细的说明,供各位码农参考.根据我自己做的进度持续更新中...... ...
- leetcode 解题报告 Word Break
Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separa ...
- LeetCode解题报告—— N-Queens && Edit Distance
1. N-Queens The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no ...
- LeetCode解题报告—— Longest Valid Parentheses
Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...
随机推荐
- OutLook中添加Exchange失败问题
问题: 在邮件中添加账户后,打开outlook时报出错误:无法启动 Microsoft Outlook. 无法打开 Outlook 窗口. 无法打开此文件夹集合. 必须先使用当前的配置文件连接到 Mi ...
- 虚拟机的安装以及Linux的学习
安装虚拟机 对虚拟机的认识 其实初中的时候我就听说过虚拟机这个名词,当时的我还小,也不知道虚拟机是个什么东西,那时我傻傻的认为虚拟机只不过是电脑中的一个虚拟的计算机,没有什么实在的作用.后来随着大学课 ...
- CentOS7.5搭建ELK6.2.4集群及插件安装
一 简介 Elasticsearch是一个高度可扩展的开源全文搜索和分析引擎.它允许您快速,近实时地存储,搜索和分析大量数据.它通常用作支持具有复杂搜索功能和需求的应用程序的底层引擎/技术. 下载地址 ...
- 数据迁移之Sqoop
一 简介 Apache Sqoop(TM)是一种用于在Apache Hadoop和结构化数据存储(如关系数据库)之间高效传输批量数据的工具 . 官方下载地址:http://www.apache.org ...
- chromiumFx编译使用
CEF chormeFx 为针对.Net的CEF框架,下载链接为: https://bitbucket.org/chromiumfx/chromiumfx 点击Download可以下载chromium ...
- N的阶乘末尾有多少个0
N的阶乘(N!)中的末尾有多少个0? N的阶乘可以分解为: 2的X次方,3的Y次方,4的5次Z方,.....的成绩.由于10 = 2 * 5,所以M只能和X和Z有关,每一对2和5相乘就可以得到一个10 ...
- 【51nod】1251 Fox序列的数量
题解 容斥题 我们枚举出现次数最多的数出现了K次 然后我们需要计算的序列是所有数字出现个数都不超过K - 1次 我们枚举不合法的数字的数目j,说明这个排列里除了我们固定出现K次的数至少有j个数是不合法 ...
- Pytho并发编程-利用协程实现简单爬虫
from gevent import monkey;monkey.patch_all() import gevent from urllib.request import urlopen def ge ...
- UVALive - 6912 Prime Switch (状压DP)
题目链接:传送门 [题意]有n个灯,m个开关,灯的编号从1~n,每个开关上有一个质数,这个开关同时控制编号为这个质数的倍数的灯,问最多有多少灯打开. [分析]发现小于根号1000的质数有10个左右,然 ...
- iOS 9应用开发教程之显示编辑文本标签文本框
iOS 9应用开发教程之显示编辑文本标签文本框 ios9显示.编辑文本 在iOS,经常会看到一些文本的显示.文字就是这些不会说话的设备的嘴巴.通过这些文字,可以很清楚的指定这些设备要表达的信息.本节将 ...