《剑指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次方.不得使用库函数,同时不需要考虑大数问题. 解题思路:最一般的方法实现数值 ...
随机推荐
- JZOJ.1002【USACO题库】1.1.3 Friday the Thirteenth黑色星期五
每日一博第一天! 保持你的决心 题目描述 13号又是星期五是一个不寻常的日子吗? 13号在星期五比在其他日少吗?为了回答这个问题,写一个程序来计算在n年里13 日落在星期一,星期二......星期日的 ...
- 【重启C++】 关于 【类】
1.什么是抽象类 带有纯虚函数成员的类,称为抽象类.抽象类不能被实例化,因为如果能实例化,调用这个纯虚的成员函数时怎么处理. 2.什么是纯虚函数 纯虚函数是在声明虚函数时被“初始化”为0的函数.声明纯 ...
- SpringCloud组件及功能介绍
1.什么是SpringClould? SpringCloud是一个基于SpringBoot实现的微服务架构开发工具.它为微服务架构中涉及的配置管理.服务治理.断路器.智能路由.微代理.控制总线. ...
- 关于centOS安装配置mysql5.6那点事
第一步 下载安装 一.主要因为现在mysql官网yum直接推送mysql8,mysql5.1,然而mysql8不稳定,mysql5.1版本又太低,要想用旧版本5.6就先下载相应的依赖包,安装好依赖包, ...
- 屹今为止最好用的HTTP客户端命令行工具-接口调试神器HTTPie
一.思考❓❔ 1.你用过哪些http客户端调试工具? Postman 不够灵活 需要打开客户端, 麻烦 学习成本高 Jmeter 臃肿 麻烦 学习成本高 curl 参数多, 记不住 不够灵活 主要在L ...
- java lesson13Homework
/** * 1. 字符串解析,现有字符串,“卡巴斯基#杀毒软件#免费版#俄罗斯#”,解析出每个元素. */ package String13Practice; public class String0 ...
- 【原创】大数据基础之Gobblin(2)持久化kafka到hdfs
gobblin 0.10 想要持久化kafka到hdfs有很多种方式,比如flume.logstash.gobblin,其中flume和logstash是流式的,gobblin是批处理式的,gobbl ...
- webmagic学习之路-1:采集安居客列表页测试
---恢复内容开始--- package com.action; import java.util.ArrayList; import java.util.List; import java.util ...
- WebStorm 使用技巧
常用快捷键 代码编辑 ctrl + d:复制行 ctrl + y:删除行 ctrl + x:剪切行 ctrl + shift + ↑: 行移动 ctrl + shift + enter: 换行 ctr ...
- linux命令详解——sed
sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换.删除.新增.选取等特定工作,下面先了解一下sed的用法 sed命令行格式为: se ...