剑指offer 第十天
37.数字在排序数组中出现的次数
统计一个数字在排序数组中出现的次数。
采用二分查找法
/*
方法一:时间复杂度O(n),不可选
*/
public class Solution {
public int GetNumberOfK(int [] array , int k) {
if(array.length == 0) return 0;
int count = 0;
for(int i = 0 ; i < array.length ; i++){
if(array[i] == k){
count++;
}else{
if(count != 0)
break;
}
}
return count;
}
}
/*
方法二:首选!先采用二分查找法,在数组中查找到第一个K和第二个K,总时间复杂度O(logn)
*/
public class Solution {
public int GetNumberOfK(int[] array,int k){
if(array.length == 0) return 0;
int first = getFirstK(array,k,0,array.length-1);
int last = getLastK(array,k,0,array.length-1);
if(first > -1 && last > -1)
return last - first + 1;
return 0;
}
public int getFirstK(int[] array,int k,int start,int end){
if(start > end) return -1;
int midIdx = (end + start)/2;
if(array[midIdx] == k){
if((midIdx > 0 && array[midIdx-1] != k) || midIdx == 0)
return midIdx;
else{
end = midIdx - 1;
return getFirstK(array,k,start,end);
}
}else if(array[midIdx] > k){
end = midIdx - 1;
}else if(array[midIdx] < k){
start = midIdx +1;
}
return getFirstK(array,k,start,end);
}
public int getLastK(int[] array,int k ,int start,int end){
if(start > end) return -1;
int midIdx = (start + end)/2;
if(array[midIdx] == k){
if((midIdx < array.length-1 && array[midIdx+1] != k) || midIdx == array.length-1)
return midIdx;
else
start = midIdx + 1;
}else if(array[midIdx] > k){
end = midIdx - 1;
}else if(array[midIdx] < k){
start = midIdx + 1;
}
return getLastK(array,k,start,end);
}
}
38.二叉树的深度
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public int TreeDepth(TreeNode root) {
if(root == null) return 0;
int left = TreeDepth(root.left);
int right = TreeDepth(root.right);
if(left>right) return left+1;
else return right+1;
}
}
39.平衡二叉树
输入一棵二叉树,判断该二叉树是否是平衡二叉树。如果某二叉树中任意节点的左、右子树的深度相差不超过1,那么他就是一棵平衡二叉树。
解法一:不够简便
public class Solution {
public boolean IsBalanced_Solution(TreeNode root) {
if(root == null) return true;
int left = TreeDepth(root.left);
int right = TreeDepth(root.right);
if((left-right)>1||(left-right)<-1)
return false;
else
return IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right);
}
public int TreeDepth(TreeNode root){
if(root == null) return 0;
int left = TreeDepth(root.left);
int right = TreeDepth(root.right);
return left > right ? left+1 : right+1;
}
}
解法二:推荐!后序遍历二叉树,只需遍历一遍即可。
public class Solution {
public boolean IsBalanced_Solution(TreeNode root) {
return getDepth(root) != -1;
}
public int getDepth(TreeNode root){
if(root == null) return 0;
int left = getDepth(root.left);
if(left == -1)
return -1;
int right = getDepth(root.right);
if(right == -1)
return -1;
return Math.abs(left-right) > 1 ? -1 : Math.max(left,right) + 1;
}
}
40.数组中只出现一次的数字
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
第一种:利用Set,空间复杂度为O(N)
//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
import java.util.HashSet;
import java.util.Iterator;
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
HashSet<Integer> set = new HashSet<Integer>();
for(int i = 0;i<array.length;i++){
if(set.contains(array[i])){
set.remove(array[i]);
}else{
set.add(array[i]);
}
}
boolean isFirst = true;
Iterator iter = set.iterator();
while(iter.hasNext()){
if(isFirst){
num1[0] = (int)iter.next();
isFirst = false;
}else
num2[0] = (int)iter.next();
}
}
}
41.数组中只出现一次的数字
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
按位运算:异或、位移
//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
int OR = 0;
for(int i = 0;i<array.length;i++)
OR ^= array[i];
int idx = 0;//OR从后数第几位是1,从1开始
while(OR != 0){
OR = OR >> 1;
idx++;
}
num1[0] = 0;
num2[0] = 0;
for(int i = 0;i<array.length;i++){
if((array[i]&(1<<(idx-1))) == 0)
num1[0] ^= array[i];
else
num2[0] ^= array[i];
}
}
}
42.和为S的连续正数序列
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
import java.util.ArrayList;
public class Solution {
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
int small = 1,big = 2,listSum = 3;
int mid = (sum+1)/2;
while(small < mid && small < big){
if(listSum == sum){ //注意此处很容易出现死循环,当检测出一个序列后,记得变化small数值
ArrayList<Integer> listResult = new ArrayList<>();
for(int i = small;i <= big;i++)
listResult.add(i);
result.add(listResult);
listSum -= small;
small++;
}else if(listSum < sum){
big++;
listSum += big;
}else if(listSum > sum){
listSum -= small;
small++;
}
}
return result;
}
}
43.和为S的两个数
输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
解析:
其实找的就是数组最两侧满足和为S的数字,因为:
z=xy
x+y=s
z=x(s-x)=sx-x^2 函数图像为向下开口的抛物线,两段数值小中间大。所以取两边的值。
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
ArrayList<Integer> result = new ArrayList<>();
int p1 = 0,p2 = array.length-1;
while(p1<p2){
if(array[p1]+array[p2] == sum){
result.add(array[p1]);
result.add(array[p2]);
return result;
}else if(array[p1]+array[p2]>sum)
p2--;
else
p1++;
}
return result;
}
}
44.坐旋转字符串
汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!
该题有好多种做法
方法一:虽然AC,但是不是最优解
public class Solution {
public String LeftRotateString(String str,int n) {
if(n<0 || str==null || str.length() == 0) return "";
n %= str.length();
StringBuilder sb = new StringBuilder();
for(int i = n;i<str.length();i++){
sb.append(str.charAt(i));
}
for(int i = 0;i<n;i++){
sb.append(str.charAt(i));
}
return sb.toString();
}
}
方法二
public class Solution {
public String LeftRotateString(String str,int n) {
if(n<0 || str==null || str.length() == 0) return "";
n %= str.length();
StringBuilder sb = new StringBuilder();
for(int i = n;i<str.length();i++){
sb.append(str.charAt(i));
}
for(int i = 0;i<n;i++){
sb.append(str.charAt(i));
}
return sb.toString();
}
}
45.翻转字符串
牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?
public class Solution {
public String ReverseSentence(String str) {
if(str.length()==0) return "";
char[] charArray = str.toCharArray();
Reverse(charArray,0,str.length()-1);
int start = 0,end = 0;
for(int i = 0;i < charArray.length;i++){
if(charArray[i] == ' '){
end = i-1;
Reverse(charArray,start,end);
start = i+1;
}
}
Reverse(charArray,start,charArray.length-1);
return String.valueOf(charArray);
}
public char[] Reverse(char[] charArray,int start,int end){
while(start<end){
char temp = charArray[start];
charArray[start] = charArray[end];
charArray[end] = temp;
start++;
end--;
}
return charArray;
}
}
剑指offer 第十天的更多相关文章
- 剑指Offer(十八):二叉树的镜像
剑指Offer(十八):二叉树的镜像 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/baidu ...
- 剑指Offer(十九):顺时针打印矩阵
剑指Offer(十九):顺时针打印矩阵 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/baid ...
- 剑指offer三十五之数组中的逆序对
一.题目 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...
- 剑指offer五十二之正则表达式匹配
一.题目 请实现一个函数用来匹配包括'.'和'*'的正则表达式.模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次). 在本题中,匹配是指字符串的所有字符匹配整个模式 ...
- 剑指offer二十二之从上往下打印二叉树
一.题目 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 二.思路 二叉树的层次遍历,可以借助队列实现.具体思路详见注释. 三.代码 import java.util.ArrayList; i ...
- 剑指Offer(十九)——顺时针打印矩阵
题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字. 例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 ...
- 剑指offer二十之包含min函数的栈
一.题目 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数. 二.思路 用一个栈dataStack保存数据,用另外一个栈minStack保存依次入栈最小的数.每次元素存入minSt ...
- 剑指offer六十之按之把二叉树打印成多行
一.题目 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行.二.思路 队列LinkedList完成层序遍历,用end记录每层结点数目 三.代码 import java.util.Arra ...
- 剑指offer五十九之按之字形顺序打印二叉树
一.题目 请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推.二.思路 详见代码 三.代码 import j ...
随机推荐
- 洛谷 [P2764]最小路径覆盖问题
二分图应用模版 #include <iostream> #include <cstdio> #include <algorithm> #include <cs ...
- ORM规约变更经典案例---mysql军规
先介绍一下<MySQL数据库开发的三十六条军规>,这里只介绍核心的,具体内容大家可以自行百度,这是从底层开发人员到管理者必须知道规范.出自58赶集. 写在前面的话: 总是在灾难发生后,才想 ...
- python重新利用shodan API
前言: 之前写过一个shodan的API调用 感觉写的不这么好.然后现在重新写一个 shodan介绍: shodan是互联网上最可怕的搜索引擎. CNNMoney的一篇文章写道,虽然目前人们都认为谷歌 ...
- MySQL数据库基础
MySQL数据库基础 本文的所有操作是基于CMD环境,MySQL通过在命令行中输入SQL语句对数据库进行操作.配置问题可参考<打通MySQL的操作权限>中的内容,该文算是针对前期的环境配置 ...
- Mac下安装php5.6/7.1
安装环境 OS X EI Capitan 10.11.4 Homebrew安装 homebrew是一个类似于ubuntu中apt-get的一个软件管理器,安装比较简单,在命令行中输入如下代码: rub ...
- Django——ContentType及ContentType-signals的使用
一.ContentType 在django中,有一个记录了项目中所有model元数据的表,就是ContentType,表中一条记录对应着一个存在的model,所以可以通过一个ContentType表的 ...
- Android app性能测试小结(7个性能指标)
1.性能测试的几个指标: 2.性能测试环境准备: 3.启动时间 3.1,监控值的获取方法 启动分为冷启动和热启动,冷启动:应用程序首次启动,进程首次创建并加载资源的过程:热启动:应用程序启 ...
- POJ - 2253 Frogger 单源最短路
题意:给定n个点的坐标,问从第一个点到第二个点的最小跳跃范围.d(i)表示从第一个点到达第i个点的最小跳跃范围. AC代码 #include <cstdio> #include <c ...
- 编码问题 php字符编码转换类
各种平台和软件打开显示的编码问题,需要使用不同的编码,根据我们不同的需求. php 字符编码转换类,支持ANSI.Unicode.Unicode big endian.UTF-8.UTF-8+Bom ...
- Luogu P1522 牛的旅行 Cow Tours
题目描述 农民 John的农场里有很多牧区.有的路径连接一些特定的牧区.一片所有连通的牧区称为一个牧场.但是就目前而言,你能看到至少有两个牧区通过任何路径都不连通.这样,Farmer John就有多个 ...