按照个人计划,从今天开始做《剑指offer》上面的算法题,练习平台为牛客网,上面对每道题都有充分的测试实例,感觉还是很不错的。今天下午做了四道题,分别为:

1. 二叉树的深度(书55题)

二叉树的深度

判断平衡二叉树

2. 数组中数字出现的次数(书56题)

  数组中只出现一次的两个数字

3. 和为S的数字(书57题)

  和为S的连续正数序列

  和为S的两个数字

4. 翻转字符串(书58题)

  左旋转字符串

  翻转单词顺序列

二叉树类型的问题在leetcode上多次遇到,剑指上的题也比较简单,这边就不再说明,只在最后贴出代码,需要注意的是判断平衡二叉树如何使用一次遍历来判断(利用后序遍历,从叶节点往上判断)。

和为S的数字利用的是Two Pointers的思想,也算比较容易,所以今天的重点是第2,4题。

2. 数组中数字出现的次数

  1. 题目描述:一个整型数组里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

本题采用位运算,与leetcode上137. Single Number II类似,且在Discuss中有大神贴出了解法和数学解释,感兴趣的同学可以了解一下。与leetcode上不同的是,本题有两个数字只出现一次,因此较为麻烦。

  1. 思路:
  2.  
  3. 如果能把原数组分为两个只有一个数字出现的子数组,就能够用异或运算得出这两个数。
  4.  
  5. 从头到尾异或数组中的每个数字,最终得到两个只出现一次的数字的异或结果。
  6.  
  7. 由于这两个数字不一样,异或的结果肯定不为0,也就是说这个结果数字的二进制表示中至少有一位为1
  8.  
  9. 在结果数字中找到第一个为1的位的位置,记为第n位,以第n位是不是1为标准把原数组中的数字分成两个子数组,第一个子数组中每个数字的第n位都是1,而第二个子数组中每个数字的第n位都是0。这样,就把原数组分为了两个子数组,在每个子数组中只有一个数出现一次,其他数字都出现了两次。

实现代码:

  1. //num1,num2分别为长度为1的数组。传出参数
  2. //将num1[0],num2[0]设置为返回结果
  3. public class Solution {
  4. public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
  5. int t = 0; //第一轮异或的结果
  6. for(int n:array){
  7. t ^= n;
  8. }
  9. int firstOne = FindFirstOne(t);//找到第一位1的位置
  10. num1[0] = 0;
  11. num2[0] = 0;
  12. for(int n:array){
  13. if(IsBit1(n,firstOne)){//根据第n位是否为1将数组分开
  14. num1[0] ^= n;
  15. }else{
  16. num2[0] ^= n;
  17. }
  18. }
  19. }
  20.  
  21. public int FindFirstOne(int t){
  22. int first = 0;
  23. while((t & 1) == 0 && first < 32){//int型为32位
  24. t = t>>1;
  25. first++;
  26. }
  27. return first;
  28. }
  29.  
  30. public boolean IsBit1(int num,int indexBit){
  31. num = num >> indexBit;
  32. return (num & 1) == 1;
  33. }
  34. }

4. 翻转字符串

  1. 题目描述:
  2.  
  3. 翻转单词顺序:
  4.  
  5. 输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。
  6.  
  7. 为简单起见,标点符号和普通字母一样处理。如“I am a student.”,则输出为"student. a am I"
  8.  
  9. 左旋转字符串:
  10.  
  11. 把字符串前面的若干个字符转移到字符串的尾部。
  12.  
  13. 如输入"abcdefg"和数字2,则输出“cdefgab”。

这题考察的如何灵活的运用字符串翻转来处理新的问题,下面给出字符串翻转的实现代码,代码中,字符串首先被转化为字符数组再进行操作。

  1. public void ReverseString(char[] array,int start,int end){
  2. if(start >= end)
  3. return;
  4. while(start < end){
  5. char tmp = array[start];
  6. array[start] = array[end];
  7. array[end] = tmp;
  8. start++;
  9. end--;
  10. }
  11. }

思路如下:

  1. 翻转单词顺序:
  2.  
  3. 首先将句子中的所有字符翻转,如"I am a student."翻转得到".tneduts a ma I"
  4.  
  5. 再将句子内的单词翻转回来得到"student. a am I"
  6.  
  7. 左旋转字符串:
  8. "abcdefg"为例,把字符串根据n分为两部分
  9. 先对每一部分分别翻转,得到"bagfedc"
  10.  
  11. 然后再对整个字符串进行翻转,得到"cdefgab"

代码如下:

翻转单词顺序:

  1. public String ReverseSentence(String str) {
  2. char[] array = str.toCharArray();
  3. ReverseString(array,0,array.length-1);
  4. int s = 0;
  5. for(int end = 0; end < array.length; end++){
  6. if(array[end] == ' '){
  7. ReverseString(array,s,end-1);
  8. s = end+1;
  9. }
  10. }
  11. ReverseString(array,s,array.length-1);
  12. return String.valueOf(array);
  13. }

左旋转字符串:

  1. public String LeftRotateString(String str,int n) {
  2. int len = str.length();
  3. if(len <= 1 || n%len == 0) return str;
  4. n %= len;
  5. char[] array = str.toCharArray();
  6. ReverseString(array,0,n-1);
  7. ReverseString(array,n,len-1);
  8. ReverseString(array,0,len-1);
  9. return String.valueOf(array);
  10. }

最后贴上第1和第3题的代码:

二叉树:

  1. //二叉树的深度
  2. public class Solution {
  3. public int TreeDepth(TreeNode root) {
  4. if(root == null)
  5. return 0;
  6. int left = TreeDepth(root.left);
  7. int right = TreeDepth(root.right);
  8. return Math.max(left,right)+1;
  9. }
  10. }
  11.  
  12. //判断平衡二叉树
  13. public class Solution {
  14. public boolean IsBalanced_Solution(TreeNode root) {
  15. if(root == null)
  16. return true;
  17. return maxDepth(root) != -1;
  18. }
  19.  
  20. public int maxDepth(TreeNode node){
  21. if(node == null)
  22. return 0;
  23. int left = maxDepth(node.left);
  24. int right = maxDepth(node.right);
  25. if(left == -1 || right == -1 || Math.abs(left-right) > 1){
  26. return -1;
  27. }
  28. return Math.max(left,right)+1;
  29. }
  30. }

和为S的数字:

  1. //和为S的两个数字
  2. import java.util.ArrayList;
  3. public class Solution {
  4. public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
  5. ArrayList<Integer> res = new ArrayList();
  6. if(array.length == 0) return res;
  7. int head = 0, tail = array.length-1;
  8. while(head < tail){
  9. int p = array[head];
  10. int q = array[tail];
  11. if(p+q == sum){
  12. res.add(p);
  13. res.add(q);
  14. break;
  15. }else if(p+q > sum){
  16. tail --;
  17. }else{
  18. head ++;
  19. }
  20. }
  21. return res;
  22. }
  23. }
  24.  
  25. //和为S的连续正数序列
  26. import java.util.ArrayList;
  27. public class Solution {
  28. public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
  29. int small = 1, big = 2, mid = (sum+1)/2;
  30. ArrayList<ArrayList<Integer>> res = new ArrayList();
  31. ArrayList<Integer> tmp = new ArrayList();
  32. tmp.add(small);
  33. tmp.add(big);
  34. int total = small+big;
  35. while(small < mid){
  36. if(total == sum){
  37. res.add(new ArrayList(tmp));
  38. }
  39. if(total > sum){
  40. total -= small;
  41. small++;
  42. tmp.remove(0);
  43. }else{
  44. big++;
  45. total += big;
  46. tmp.add(big);
  47. }
  48. }
  49. return res;
  50. }
  51. }

《剑指offer》算法题第一天的更多相关文章

  1. 剑指offer算法题

    数组中只出现一次的数字(一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字): 解法在于位运算中的异或,直接异或可以得到这两个数的异或,按照最后的有效数字位可以 ...

  2. 剑指offer算法总结

    剑指offer算法学习总结 节选剑指offer比较经典和巧妙的一些题目,以便复习使用.一部分题目给出了完整代码,一部分题目比较简单直接给出思路.但是不保证我说的思路都是正确的,个人对算法也不是特别在行 ...

  3. 剑指Offer编程题1——二维数组中的查找

    剑指Offer编程题1---------------二维数组中的查找 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完 ...

  4. 剑指Offer——算法复杂度中的O(logN)底数是多少

    剑指Offer--算法复杂度中的O(logN)底数是多少 前言 无论是计算机算法概论.还是数据结构书中,关于算法的时间复杂度很多都用包含O(logN)这样的描述,但是却没有明确说logN的底数究竟是多 ...

  5. 剑指Offer编程题2——替换空格

    剑指Offer编程题2——替换空格 题目描述 请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happ ...

  6. 剑指offer编程题66道题 36-66

    36.两个链表的第一个公共节点 题目描述 输入两个链表,找出它们的第一个公共结点. 1.具有重合节点的两个链表是一个Y字性,用两个堆栈放这两个链表,从尾部开始遍历,直到遍历到最后一个重合节点. 这种算 ...

  7. 牛客网剑指offer刷题总结

    二维数组中的查找: 题目描述:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 两 ...

  8. LeetCode剑指Offer刷题总结(一)

    LeetCode过程中值得反思的细节 以下题号均指LeetCode剑指offer题库中的题号 本文章将每周定期更新,当内容达到10题左右时将会开下一节. 二维数组越界问题04 public stati ...

  9. 剑指offer刷题(Tree)

    开篇 二刷剑指offer了,本来用Tyora记的笔记,发现字数到四万了就变得好卡o(╥﹏╥)o,刚好开始写博客,就转过来吧,记下来子自己看.不废话,开刷... JZ26. 树的子结构 输入两棵二叉树A ...

  10. 剑指offer刷题

    1.面试题43. 1-n整数中1出现的次数 输入一个整数 n ,求1-n这n个整数的十进制表示中1出现的次数. 例如,输入12,1-12这些整数中包含1 的数字有1.10.11和12,1一共出现了5次 ...

随机推荐

  1. 多线程--CreateThread与_beginthreadex本质区别

    转载 MoreWindows: 秒杀多线程第二篇 本文将带领你与多线程作第一次亲密接触,并深入分析 CreateThread与_beginthreadex的本质区别,相信阅读本文后你能轻松的使用多线程 ...

  2. PTA(Advanced Level)1011.World Cup Betting

    With the 2010 FIFA World Cup running, football fans the world over were becoming increasingly excite ...

  3. Go语言流程控制中的break,continue和goto(七)

    break(跳出循环) break用于跳出整个循环,如下: func main() { ;i<;i++{ { break } fmt.Println(i) } } // 0 1 2 3 代码里只 ...

  4. # 数字签名&数字证书

    目录 数字签名&数字证书 数字签名 数字证书 数字证书的实例(https协议) 数字签名&数字证书 参考资料: 数字签名是什么?-阮一峰的网络日志 数字签名和数字证书究竟是什么?知乎- ...

  5. oracle 重置密码(一般电网,国企需要的二级等保)

    oracle 10g,11g 可以查找以下,12c没有测试 一.查看profile配置并记录;二.在重置密码之前修改profile(PASSWORD_REUSE_MAX.PASSWORD_REUSE_ ...

  6. sql server 函数详解(5)系统函数

    返回表中指定字段的长度 返回表中指定字段的名称   返回数据表达式的数据的实际长度函数 返回数据库的编号   返回数据库的名称   返回数据库当前默认的null值 返回服务器端计算机的标识号 返回服务 ...

  7. wex5 file文件存储

    在js中需要引入file的cordova包 require("cordova!cordova-plugin-file"); 如果要存到手机的根目录下,在Native文件夹的对应项目 ...

  8. STM32F10xxx_启动模式

    目录 STM32F10xxx_启动模式 更新记录 启动配置 参考: STM32F10xxx_启动模式 更新记录 version status description date author V1.0 ...

  9. Linux安装Redis、PHP安装Redis扩展模块

    Redis的官方下载: http://redis.io/download   步骤一:下载安装包  步骤二:编译源程序  步骤三:移动文件.便于管理  步骤四:启动 Redis服务  查看是否启动成功 ...

  10. vim 搜索 向前,向后

    vim 搜索可以是 / 或者 ?,前者是往下找,后者是往前找. 用 n 查找下一个的时候,就和这两个指令指定的方向相同.如果你想改变方向的话,比如想往下找,那么 / 完了直接回车就行了.表示再次使用上 ...