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 第十天的更多相关文章

  1. 剑指Offer(十八):二叉树的镜像

    剑指Offer(十八):二叉树的镜像 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/baidu ...

  2. 剑指Offer(十九):顺时针打印矩阵

    剑指Offer(十九):顺时针打印矩阵 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/baid ...

  3. 剑指offer三十五之数组中的逆序对

    一.题目 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...

  4. 剑指offer五十二之正则表达式匹配

    一.题目 请实现一个函数用来匹配包括'.'和'*'的正则表达式.模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次). 在本题中,匹配是指字符串的所有字符匹配整个模式 ...

  5. 剑指offer二十二之从上往下打印二叉树

    一.题目 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 二.思路 二叉树的层次遍历,可以借助队列实现.具体思路详见注释. 三.代码 import java.util.ArrayList; i ...

  6. 剑指Offer(十九)——顺时针打印矩阵

    题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字. 例如,如果输入如下4 X 4矩阵: 1   2    3     4 5   6    7     8 9   10  11  ...

  7. 剑指offer二十之包含min函数的栈

    一.题目 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数. 二.思路 用一个栈dataStack保存数据,用另外一个栈minStack保存依次入栈最小的数.每次元素存入minSt ...

  8. 剑指offer六十之按之把二叉树打印成多行

    一.题目 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行.二.思路 队列LinkedList完成层序遍历,用end记录每层结点数目 三.代码 import java.util.Arra ...

  9. 剑指offer五十九之按之字形顺序打印二叉树

    一.题目 请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推.二.思路 详见代码 三.代码 import j ...

随机推荐

  1. Linux系统zookeeper环境搭建(单机、伪分布式、分布式)

    本人现在对zookeeper的环境搭建做一个总结,一般zookeeper的安装部署可以有三种模式,单机模式.伪分布式和分布式,这三种模式在什么时候应用具体看大家的使用场景,如果你只有一台机器且只是想自 ...

  2. NOIP 2017 day -1 杂记

    我几乎要崩溃了. 写任何板子都是第一遍一定写不对,后来发现是傻逼性错误. 好奇怪的,这些东西明明我都会,为什么现在我都忘了? 很烦.现在心里特别乱,写什么都写不下去. 可能我是真的无法放心这次的比赛. ...

  3. [Lucas定理]【学习笔记】

    Lucas定理 [原文]2017-02-14 [update]2017-03-28 Lucas定理 计算组合数取模,适用于n很大p较小的时候,可以将计算简化到小于p $ \binom{n}{m} \m ...

  4. win2012 配置wamp的若干错误

    转自群友 VC2015.VC14 在 Windows 2012 R2 安装失败,0x80240017 - 未指定的错误,解决办法据朋友反应VC2013一样存在这个问题--查资料说是没有安装 KB299 ...

  5. 为Android添加JNI支持

    起因 今天在进行Android原生开发时,需要通过JNI调用C++代码实现一些处理.以前没有做过类似的东西,在网上找了很久才解决问题,特记录下来以便以后翻阅. Eclipse无cygwin编译so的方 ...

  6. [Python Study Notes]cpu信息

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ...

  7. Mac 上安装 GCC

    https://www.zhihu.com/question/20588567 安装 添加bin路径到$PATH变量

  8. TJ4运行环境

    http://springwq2011.blog.51cto.com/4332889/966028 http://blog.csdn.net/u013573789/article/details/45 ...

  9. C++11 标准库也有坑(time-chrono)

    恰巧今天调试程序遇到时间戳问题, 于是又搜了搜关于取时间戳,以及时间戳转字符串的问题, 因为 time()   只能取到秒(win和linux) 想试试看能不能找到 至少可以取到毫秒的, 于是, 就找 ...

  10. CENTOS6.6下mysql5.7.11带boost和不带boost的源码安装

    本文来自我的github pages博客http://galengao.github.io/ 即www.gaohuirong.cn Mysql5.7版本更新后有很多变化,比如json等,连安装都有变化 ...