目录
- 剑指 Offer 05. 替换空格
- 剑指 Offer 06. 从尾到头打印链表
- 剑指 Offer 09. 用两个栈实现队列
- 剑指 Offer 10- I. 斐波那契数列
- 剑指 Offer 10- I. 斐波那契数列
- 剑指 Offer 15. 二进制中1的个数
- 剑指 Offer 17. 打印从1到最大的n位数
- 剑指 Offer 22. 链表中倒数第k个节点
- 剑指 Offer 24. 反转链表
- 剑指 Offer 25. 合并两个排序的链表
- 剑指 Offer 27. 二叉树的镜像
- 剑指 Offer 54. 二叉搜索树的第k大节点
- 剑指 Offer 55 - I. 二叉树的深度
- 剑指 Offer 57. 和为s的两个数字
- 剑指 Offer 57 - II. 和为s的连续正数序列
- 剑指 Offer 58 - I. 翻转单词顺序
- 剑指 Offer 58 - II. 左旋转字符串
- 剑指 Offer 68 - II. 二叉树的最近公共祖先
题目:
java代码
剑指 Offer 05. 替换空格
题目:
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
java代码
class Solution {
public String replaceSpace(String s) {
//return s.replace(" ","%20"); //替换函数
StringBuilder res = new StringBuilder();
for(int i = 0; i < s.length(); i++){//拼接,空格时拼接%20
char ch = s.charAt(i);
if(ch == ' '){
res.append("%20");
}
else{
res.append(ch);
}
}
return res.toString();
}
}
剑指 Offer 06. 从尾到头打印链表
题目:
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
java代码
class Solution {
public int[] reversePrint(ListNode head) {
int total = 0;
ListNode p1 = head;
while(p1 != null){//统计链表长度
p1 = p1.next;
total++;
}
p1 = head;
int[] res = new int[total];
for(int i = total - 1; i >= 0; i--){//逆序存储链表中的值
res[i] = p1.val;
p1 = p1.next;
}
return res;
}
}
剑指 Offer 09. 用两个栈实现队列
题目:
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
java代码
class CQueue {
LinkedList<Integer> A, B;
//Deque<Integer>stack1;//java stack线程安全,比较慢
public CQueue() {
A = new LinkedList<Integer>();//此时存放是队列的后面部分,用来入队
B = new LinkedList<Integer>();//此时存放是队列的前面部分,用来出队
}
public void appendTail(int value) {
A.addLast(value);//尾添加,模拟入栈
}
public int deleteHead() {
if(B.isEmpty()) {//B是空的.需要将A中出栈在入栈,此时存放是队列的前面部分
if(A.isEmpty()) {
return -1;
}else {
while(!A.isEmpty()) {
B.addLast(A.removeLast());
}
return B.removeLast();
}
}else {//B非空,直接弹出前面部分
return B.removeLast();
}
}
}
剑指 Offer 10- I. 斐波那契数列
题目:
写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下:
F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
java代码
剑指 Offer 10- I. 斐波那契数列
题目:
java代码
剑指 Offer 15. 二进制中1的个数
题目:
请实现一个函数,输入一个整数(以二进制串形式),输出该数二进制表示中 1 的个数。例如,把 9 表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。
java代码
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
//return Integer.bitCount(n);
int res = 0;
while(n != 0){
res++;
n &= n-1;
}
return res;
}
}
剑指 Offer 17. 打印从1到最大的n位数
题目:
输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
java代码
class Solution {
public int[] printNumbers(int n) {
int total = 9;//计算最大的数是多少
for(int i= 1; i < n; i++){
total = total*10+9;
}
int[] res = new int[total];//生成数组
for(int i = 0; i < total; i++){
res[i] = i+1;
}
return res;
}
}
剑指 Offer 22. 链表中倒数第k个节点
题目:
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
java代码
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode p1 = head;//快指针
ListNode p2 = head;//慢指针
while(k > 0){//向前唯一k位,快慢指针相差k位
p1 = p1.next;
k--;
}
while(p1 != null){//同时向后移,快指针为空,慢指针指向倒数第k个
p1 = p1.next;
p2 = p2.next;
}
return p2;
}
}
剑指 Offer 24. 反转链表
题目:
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
java代码
class Solution {
public ListNode reverseList(ListNode head) {
ListNode p1 = null;
ListNode p2 = head;
while(p2 != null){
ListNode tmp = p2.next;
p2.next = p1;
p1 = p2;
p2 = tmp;
}
return p1;
}
}
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null) {
return head;
}
ListNode node = reverseList(head.next);
head.next.next = head;
head.next = null;
return node;
}
}
剑指 Offer 25. 合并两个排序的链表
题目:
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
java代码
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode res = new ListNode(0);//头结点
ListNode p1 = res;
while(l1 != null && l2 != null){//谁小,放在前面
if(l1.val < l2.val){
p1.next = l1;
p1 = p1.next;
l1 = l1.next;
}else{
p1.next = l2;
p1 = p1.next;
l2 = l2.next;
}
}
if(l1 != null){//把剩下的部分连接在后面
p1.next = l1;
}
if(l2 != null){
p1.next = l2;
}
return res.next;
}
}
剑指 Offer 27. 二叉树的镜像
题目:
请完成一个函数,输入一个二叉树,该函数输出它的镜像。
java代码
class Solution {
public TreeNode mirrorTree(TreeNode root) {
if(root == null){
return null;
}
mirrorTree(root.left); //左遍历
mirrorTree(root.right);//右遍历
//交换左右节点
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
return root;
}
}
剑指 Offer 54. 二叉搜索树的第k大节点
题目:
给定一棵二叉搜索树,请找出其中第k大的节点。
java代码
class Solution {
int count = 0; //统计遍历了多少次
int res = 0;//保存结果
public int kthLargest(TreeNode root, int k) {
dfs(root, k);
return res;
}
private void dfs(TreeNode root, int k){
if(root == null){
return;
}
//右根左遍历,从大到小
dfs(root.right, k);
if(++count == k){//第k大时,保存结果
res = root.val;
return;
}
dfs(root.left, k);
}
}
剑指 Offer 55 - I. 二叉树的深度
题目:
输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。
java代码
class Solution {
public int maxDepth(TreeNode root) {
if(root == null){
return 0;
}
return Math.max(maxDepth(root.left),maxDepth(root.right))+1;
}
}
剑指 Offer 57. 和为s的两个数字
题目:
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。
java代码
class Solution {
public int[] twoSum(int[] nums, int target) {
int i = 0;
int j = nums.length - 1;
while(i < j){
int sum = nums[i] + nums[j];
if(sum < target){// 两数之和 < 目标值,小数指针后移
i++;
}else if(sum > target){// 两数之和 > 目标值,大数指针前移
j--;
}else{// 两数之和 == 目标值,返回这两个数
return new int[] {nums[i], nums[j]};
}
}
return new int[0];
}
}
剑指 Offer 57 - II. 和为s的连续正数序列
题目:
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
java代码
class Solution {
public int[][] findContinuousSequence(int target) {
int i = 1;//区间左边界
int j = 2;//区间右边界
int sum = i + j;
List<int[]> res = new LinkedList<>();
while(i < j){
if(sum < target){//和小,需要扩大,右边界向右移动
j++;
sum += j;
}
else if(sum > target){//和大,需要缩小,左边界向右移动
sum -= i;
i++;
}
else{//保存正确的区间
int[] arr = new int[j-i+1];
for(int k = i; k <= j; k++){
arr[k-i] = k;
}
res.add(arr);
sum -= i;//左边界向右移动
i++;
}
}
return res.toArray(new int[res.size()][]);
}
}
剑指 Offer 58 - I. 翻转单词顺序
题目:
输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. “,则输出"student. a am I”。
java代码
class Solution {
public String reverseWords(String s) {
String[] strs = s.trim().split(" ");//分词
StringBuilder res = new StringBuilder();//字符串连接更快
int len = strs.length;
for(int i = len-1; i >= 0; i--){//逆向连接
String str = strs[i].trim();
if(str.equals("")){
continue;
}
res.append(str);
res.append(" ");
}
return res.toString().trim();
}
}
剑指 Offer 58 - II. 左旋转字符串
题目:
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
java代码
class Solution {
public String reverseLeftWords(String s, int n) {
if(s.equals("")){
return "";
}
return s.substring(n,s.length())+s.substring(0,n);
}
}
剑指 Offer 68 - II. 二叉树的最近公共祖先
题目:
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
java代码
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null){
return null;
}
if(p.val == root.val || q.val == root.val){
return root;
}
TreeNode left = lowestCommonAncestor(root.left , p , q);
TreeNode right = lowestCommonAncestor(root.right , p , q);
if(left != null && right != null){//p q 一个在左子树 一个在右子树 那么当前节点即是最近公共祖先
return root;
}else if(left == null && right != null){//2、p q 都在右子树
return right;
}else if(left != null && right == null){//3、p q 都在左子树
return left;
}else{
return null;
}
}
}