《剑指offer》算法题第十天
今日题目:
- 数组中的逆序对
- 两个链表的第一个公共节点
- 数字在排序数组中出现的次数
- 二叉搜索树的第k大节点
- 字符流中第一个不重复的字符
1. 数组中的逆序对
题目描述:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。 思路:
这道题运用归并排序的思想来求解,归并排序是面试中经常问到的知识点,得经常翻出来熟悉熟悉。
代码如下:
public class Solution {
int cnt; public int InversePairs(int[] array) {
cnt = 0;
if (array != null)
mergeSortUp2Down(array, 0, array.length - 1);
return cnt;
} /*
* 归并排序(从上往下)
*/
public void mergeSortUp2Down(int[] a, int start, int end) {
if (start >= end)
return;
int mid = (start + end) >> 1; mergeSortUp2Down(a, start, mid);
mergeSortUp2Down(a, mid + 1, end); merge(a, start, mid, end);
} /*
* 将一个数组中的两个相邻有序区间合并成一个
*/
public void merge(int[] a, int start, int mid, int end) {
int[] tmp = new int[end - start + 1]; int i = start, j = mid + 1, k = 0;
while (i <= mid && j <= end) {
if (a[i] <= a[j])
tmp[k++] = a[i++];
else {
tmp[k++] = a[j++];
cnt += mid - i + 1; // core code, calculate InversePairs............
cnt %= 1000000007;
}
} while (i <= mid)
tmp[k++] = a[i++];
while (j <= end)
tmp[k++] = a[j++];
for (k = 0; k < tmp.length; k++)
a[start + k] = tmp[k];
}
}
2.两个链表中的第一个公共节点
题目描述:
输入两个链表,找出它们的第一个公共结点。 思路:
《剑指offer》中的参考答案利用了两个栈来分别存储两个链表,然后从链尾到链头遍历两个链表,寻找公共的节点。但是博主觉得没必要那么麻烦,运用一个hashset就能够处理这道题。
另外,在这道题的讨论区中,有一个特别精妙的方法,利用两个指针遍历数组,第一趟得到链表长度的差值,第二趟寻找公共节点,下面也会贴出来。
代码如下:
//利用hashset
import java.util.HashSet;
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if(pHead1 == null || pHead2 == null) return null;
HashSet<ListNode> set = new HashSet();
while(pHead1 != null){
set.add(pHead1);
pHead1 = pHead1.next;
}
while(pHead2 != null){
if(set.contains(pHead2))
return pHead2;
pHead2 = pHead2.next;
}
return null;
}
} //两个指针的方法
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode p1 = pHead1;
ListNode p2 = pHead2;
while(p1 != p2){
p1 = (p1==null ? pHead2 : p1.next);
p2 = (p2==null ? pHead1 : p2.next);
}
return p1;
}
}
3.数字在排序数组中出现的次数
题目描述:
统计一个数字在排序数组中出现的次数。 思路:
比较直接的方法是直接遍历数组,统计目标数字出现的次数,时间复杂度为O(n)。
比较快的方法是利用二分查找的思想,时间复杂度可达到O(logn)。
代码如下:
public class Solution {
int count = 0;
public int GetNumberOfK(int [] array , int k) {
binSearch(array,k,0,array.length-1);
return count;
} public void binSearch(int[] nums,int k,int start,int end){
if(start == end){
if(nums[start] == k) count++;
return;
}else if(start < end){
int mid = (start+end)/2;
if(nums[mid] == k){
count++;
binSearch(nums,k,start,mid-1);
binSearch(nums,k,mid+1,end);
}else if(nums[mid] < k){
binSearch(nums,k,mid+1,end);
}else{
binSearch(nums,k,start,mid-1);
}
}
}
}
4.二叉搜索树的第k大节点
题目描述:
给定一颗二叉搜索树,请找出其中的第k大的结点。例如, 5 / \ 3 7 /\ /\ 2 4 6 8 中,按结点数值大小顺序第三个结点的值为4。 思路:
比较直接,二叉树的中序遍历。不过需要提一下的是,二叉树三种遍历顺序的递归和迭代实现方式都得非常熟悉。
代码如下:
import java.util.Stack;
public class Solution {
TreeNode KthNode(TreeNode pRoot, int k){
if(pRoot == null || k == 0) return null;
Stack<TreeNode> stack = new Stack();
int count = 0;
while(pRoot != null || !stack.isEmpty()){
if(pRoot != null){
stack.push(pRoot);
pRoot = pRoot.left;
}else{
pRoot = stack.pop();
count++;
if(count == k)
return pRoot;
pRoot = pRoot.right;
}
}
return null;
}
}
5.字符流中第一个不重复的字符
题目描述:
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。 思路:
这道题和之前的求一个数据流中的中位数的题相似,重点是如何选择一个合适的数据结构来存储数据,是的插入和查询的效率都比较高。
在这道题中,《剑指offer》给的参考答案是声明一个int型的数组来存储各个字符的状态。这种思想非常地重要,应多做练习来熟悉。
代码如下:
public class Solution {
//Insert one char from stringstream
int[] map = new int[256];
int index = 1;
public void Insert(char ch)
{//0代表还未出现相应的字符,-1代表出现一次以上,其他数字代表什么时候出现
if(map[ch] == 0)
map[ch] = index;
else if(map[ch] > 0)
map[ch] = -1;
index ++;
}
//return the first appearence once char in current stringstream
public char FirstAppearingOnce()
{
int min = Integer.MAX_VALUE;
int ind = -1;
for(int i = 0; i < 256; i++){//找出大于0的最小值及其坐标
if(map[i] > 0 && map[i] < min){
min = map[i];
ind = i;
}
}
if(ind == -1)//不存在大于0的数,则没有字符出现一次
return '#';
else
return (char)ind;
}
}
《剑指offer》算法题第十天的更多相关文章
- 剑指offer算法题
数组中只出现一次的数字(一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字): 解法在于位运算中的异或,直接异或可以得到这两个数的异或,按照最后的有效数字位可以 ...
- 剑指offer算法总结
剑指offer算法学习总结 节选剑指offer比较经典和巧妙的一些题目,以便复习使用.一部分题目给出了完整代码,一部分题目比较简单直接给出思路.但是不保证我说的思路都是正确的,个人对算法也不是特别在行 ...
- 剑指Offer——算法复杂度中的O(logN)底数是多少
剑指Offer--算法复杂度中的O(logN)底数是多少 前言 无论是计算机算法概论.还是数据结构书中,关于算法的时间复杂度很多都用包含O(logN)这样的描述,但是却没有明确说logN的底数究竟是多 ...
- 剑指 offer 第一题: 二维数组中的查找
打算写 图解剑指 offer 66 题 的系列文章,不知道大家有没有兴趣
- 剑指Offer编程题2——替换空格
剑指Offer编程题2——替换空格 题目描述 请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happ ...
- 剑指Offer编程题1——二维数组中的查找
剑指Offer编程题1---------------二维数组中的查找 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完 ...
- 剑指offer编程题66道题 36-66
36.两个链表的第一个公共节点 题目描述 输入两个链表,找出它们的第一个公共结点. 1.具有重合节点的两个链表是一个Y字性,用两个堆栈放这两个链表,从尾部开始遍历,直到遍历到最后一个重合节点. 这种算 ...
- 牛客网剑指offer刷题总结
二维数组中的查找: 题目描述:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 两 ...
- LeetCode剑指Offer刷题总结(一)
LeetCode过程中值得反思的细节 以下题号均指LeetCode剑指offer题库中的题号 本文章将每周定期更新,当内容达到10题左右时将会开下一节. 二维数组越界问题04 public stati ...
- 剑指offer编程题Java实现——面试题11数值的整数次方
题目: 实现函数double power(double base,int exponent),求base的exponent次方.不得使用库函数,同时不需要考虑大数问题. 解题思路:最一般的方法实现数值 ...
随机推荐
- 解决MFC实际运行对话框与测试对话框显示效果不一致问题
1.打开#include "stdafx.h"头文件文档 2.在末尾加上#define _UNICODE即可
- C++中如何调用DLL文件
一.动态链接库简介 动态库链接库英文位DLL,是Dynamic Link Library的缩写形式,DLL不是可执行文件.动态链接提供了一种方法,使进程可以调用不属于其可执行文件代码的函数.函数可执行 ...
- 初识WSGI接口
WSGI WSGI全称为Web Server Gateway Interface,WSGI允许web框架和web服务器分开,可以混合匹配web服务器和web框架,选择一个适合的配对.比如,可以在Gun ...
- 记录 OpenCV 错误
最近在做一个"人脸识别"的项目,我想用OpenCV来分析图片中的人脸. 但是在测试的时候,程序报出“检测到0张脸” 可能的错误原因: 1.教程中OpenCV的版本问题,教程中用的版 ...
- webmagic学习之路-1:采集安居客列表页测试
---恢复内容开始--- package com.action; import java.util.ArrayList; import java.util.List; import java.util ...
- vue.js项目开发实战笔记001——准备工作
1,Vue.js 是一套构建用户界面的渐进式框架. 2,Vue.js 是由尤雨溪开发出的,最早发布于2014年2月. 3,引用vue.js地址一CDN: <script src="ht ...
- Django基础第三篇
一.ORM操作 1.常用字段和参数 Autofied 自增的整形字段,必填参数primary_key=True, 则成为数据库的主键,如无该字段,django自动创建 IntegerField 一个 ...
- 完美解决Uncaught SyntaxError: Unexpected end of input
Unexpected end of input 的英文意思是“意外的终止输入” 他通常表示我们浏览器在读取我们的js代码时,碰到了不可预知的错误,导致浏览器 无语进行下面的读取 通常造成这种错误的原 ...
- 如何从git上批量拉取本地当前分支的所有代码
1 我本地有一个文件_netrc文件里面存储这git的相关信息,包括用户名和密码 你可以根据自己的git相关信息配置自己的信息 2 我当前的分支是dev,我要拉取当前分支下的所有代码,编写shell脚 ...
- 浅谈WEB中的高并发
转载:https://www.cnblogs.com/guan-520/p/9575848.html 何谓高并发 高并发指的是:在同时或极短时间内,有大量的请求到达服务端,每个请求都需要服务端耗费资源 ...