稳扎稳打,可攻可守。没抓在手里的成功都是不算的。
1.删除重复的数字
/**
* 给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
* <p>
* 示例 1:
* 输入: 1->1->2
* 输出: 1->2
* <p>
* 示例 2:
* 输入: 1->1->2->3->3
* 输出: 1->2->3
*/
链表结构
public class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
做过类似的题,只是现在换了一种数据结构。最笨的办法,取出所有值,存入LinkHashSet,然后由于它没有下标,还得存入List里面然后循环拼接
public ListNode method2(ListNode head) {
if (head==null||head.next==null)return head;
LinkedHashSet<Integer> integerHashSet=new LinkedHashSet<>();
while (head != null){
integerHashSet.add(head.val);
head=head.next;
}
ArrayList<ListNode> listNodes=new ArrayList<>();
for (int i:integerHashSet){
listNodes.add(new ListNode(i));
}
ListNode listNode=listNodes.get(0);
ListNode temp=listNode;
for (int i=1;i<listNodes.size();i++){
listNode.next=listNodes.get(i);
listNode=listNode.next;
}
return temp;
}
上面这种写法真的很恶心,那另一种放法就比较人性化了,如果当前节点的下一个节点等于当前节点,那就让当前节点的下一个节点等于下下个节点。
public ListNode method1(ListNode head) {
ListNode temp = head;
while (temp != null){
if (temp.next == null){
break;
}
if (temp.next.val == temp.val){
temp.next = temp.next.next;
}else {
temp = temp.next;
}
}
return head;
}
2.合并
/**
*给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
*
* 说明:
* 初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
* 你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
*
* 示例:
* 输入:
* nums1 = [1,2,3,0,0,0], m = 3
* nums2 = [2,5,6], n = 3
* 输出: [1,2,2,3,5,6]
*/
第一种思路,先把第二个数组并到第一个数组中去,然后使用排序算法进行排序
冒泡排序,比较简单比较慢
public static void method1(int[] nums1, int m, int[] nums2, int n) {
for (int i:nums2){
nums1[m++]=i;
}
int c;
for (int i=0;i<nums1.length-1;i++){
for (int j=i+1;j<nums1.length;j++){
if (nums1[i]>nums1[j]){
c=nums1[i];
nums1[i]=nums1[j];
nums1[j]=c;
}
}
}
}
快速排序,比较麻烦比较快,数越多显得越快
public static void method2(int[] nums1, int m, int[] nums2, int n) {
for (int i:nums2){
nums1[m++]=i;
}
if(nums1.length<2)return;
quickSort(nums1,0,nums1.length-1);
}
public static void quickSort(int[] arr,int low,int high){
int i,j,temp,t;
if(low>high){
return;
}
i=low;
j=high;
//temp就是基准位
temp = arr[low];
while (i<j) {
//先看右边,依次往左递减
while (temp<=arr[j]&&i<j) {
j--;
}
//再看左边,依次往右递增
while (temp>=arr[i]&&i<j) {
i++;
}
//如果满足条件则交换
if (i<j) {
t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}
}
//最后将基准为与i和j相等位置的数字交换
arr[low] = arr[i];
arr[i] = temp;
//递归调用左半数组
quickSort(arr, low, j-1);
//递归调用右半数组
quickSort(arr, j+1, high);
}
但是无论快速排序怎么快,它的复杂度也掉不到N,因为给定的两个数组都是有序数组且第一个数组的长度可以包含第二个数组,要求排成从小到大的,那我们可以从大到小排列,从数组尾排到数组头。这样一遍循环便完事了。
public static void method3(int[] nums1, int m, int[] nums2, int n) {
int i = m-1;
int j = n-1;
int k = m+n-1;
while(i>=0&&j>=0){
if(nums1[i]>nums2[j]){
nums1[k--] = nums1[i--];
}else{
nums1[k--] = nums2[j--];
}
}
while(j>=0){
nums1[k--] = nums2[j--];
}
}
3.相同的树
/**
* 给定两个二叉树,编写一个函数来检验它们是否相同。
*
* 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
*
* 示例 1:
*
* 输入: 1 1
* / \ / \
* 2 3 2 3
*
* [1,2,3], [1,2,3]
*
* 输出: true
*
* 示例 2:
*
* 输入: 1 1
* / \
* 2 2
*
* [1,2], [1,null,2]
*
* 输出: false
*
* 示例 3:
*
* 输入: 1 1
* / \ / \
* 2 1 1 2
*
* [1,2,1], [1,1,2]
*
* 输出: false
*/
树的结构
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
该题我的第一个想法是把两颗数分别存到两个数组中,然后比较两个数组是否相等,但我发现这种方法很难实现而且复杂无比,遍历树的时候还要添加null节点,然后想到了递归,可以使用递归解决此问题,不断比较想同位置上的值,相同继续比较左右子树,不同返回false。
public static boolean method1(TreeNode p,TreeNode q){
if (p == null && q == null) {
return true;
} else if (p == null) {
return false;
} else if (q == null) {
return false;
} else if (p.val != q.val) {
return false;
}
return method1(p.left, q.left) && method1(p.right, q.right);
}
简化判断流程
public static boolean method2(TreeNode p,TreeNode q){
if(p==null && q==null){
return true;
}
if(p!=null && q!=null && p.val==q.val ){
return method2(p.left,q.left) && method2(p.right,q.right);
}else {
return false;
}
}
再次简化
public static boolean method3(TreeNode p,TreeNode q){
if(p == null) return q == null;
if(q == null||p.val!=q.val) return false;
return method3(p.left,q.left)&&method3(p.right,q.right);
}
4.对称的树
/**
* 给定一个二叉树,检查它是否是镜像对称的。
*
* 例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
*
* 1
* / \
* 2 2
* / \ / \
* 3 4 4 3
*
* 但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:
*
* 1
* / \
* 2 2
* \ \
* 3 3
*
* 说明:
* 如果你可以运用递归和迭代两种方法解决这个问题,会很加分。
*/
树的结构
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
思想和上一题一样,前面做一些判断,后面递归比较对称位置
public boolean method1(TreeNode root) {
if (root==null)return true;
if (root.left==null) return root.right==null;
if (root.right==null||root.left.val!=root.right.val)return false;
return isSame(root.left,root.right);
}
public static boolean isSame(TreeNode p, TreeNode q){
if(p == null) return q == null;
if(q == null||p.val!=q.val) return false;
return isSame(p.left,q.right)&&isSame(p.right,q.left);
}