3.hashset和hashmap

1.哈希表简单介绍

  1. 哈希表在使用它层面上可以理解为一种集合结构

  2. 如果只有key,没有伴随数据value,可以使用hashSet结构(c++中叫unorderset)

  3. 如果有key,有伴随数据value,可以使用hashMap结构(c++中叫unorderMap)

  4. 有无伴随数据,是hashMap和hashSet唯一的区别,底层的实际结构是一回事。

  5. 使用哈希表增(put),删除(remove),改(put),查(get)的操作,可以认为时间复杂度为O(1),但是常数时间比较大。

  6. 放入哈希表的东西,如果是基础类型,内部按值传递,内存占用就是改值的实际大小。

  7. 放入哈希表的东西,不是基础类型,内部按照引用传递,内存占用就是这个东西的内存地址大小。

HashMap跟HashSet

HashSet:

HashSet实现了Set接口,它不允许集合中出现重复元素。当我们提到HashSet时,第一件事就是在将对象存储在HashSet之前,要确保重写hashCode()方法和equals()方法,这样才能比较对象的值是否相等,确保集合中没有

储存相同的对象。如果不重写上述两个方法,那么将使用下面方法默认实现:

public boolean add(Object obj)方法用在Set添加元素时,如果元素值重复时返回 “false”,如果添加成功则返回"true"

HashMap:

HashMap实现了Map接口,Map接口对键值对进行映射。Map中不允许出现重复的键(Key)。Map接口有两个基本的实现

TreeMap和HashMap
TreeMap保存了对象的排列次序,而HashMap不能。HashMap可以有空的键值对(Key(null)-Value(null))

HashMap非线程安全的(非Synchronize),要想实现线程安全,那么需要调用collections类的静态方法synchronizeMap()实现。

public Object put(Object Key,Object value)方法用来将元素添加到map中。

HashSet与HashMap的区别:

在这里插入图片描述

HashMap使用键(Key)计算Hashcode. HashSet使用成员对象来计算hashcode值,. 对于两个对象来说hashcode可能相同,. 所以equals ()方法用来判断对象的相等性,. 如果两个对象不同的话,那么返回false. HashMap相对于HashSet较快,因为它是使用唯一的键获取对象. HashSet较HashMap来说比较慢.

2.有序表

有序表的操作都是O(logn)级别

在这里插入图片描述

在这里插入图片描述

//有序表
//常见的操作
TreeMap<Integer, String> treeMap1 = new TreeMap<>();

treeMap1.put(7, "我是7");
treeMap1.put(6, "我是6");
treeMap1.put(3, "我是3");
treeMap1.put(5, "我是5");
treeMap1.put(3, "我是3");
treeMap1.put(7, "我是7");
treeMap1.put(2, "我是2");
treeMap1.put(3, "我是3");

System.out.println(treeMap1.containsKey(5));
System.out.println(treeMap1.get(5));
System.out.println(treeMap1.firstKey() + "我最小");
System.out.println(treeMap1.lastKey() + " 我最大");
System.out.println(treeMap1.floorKey(8) + "在表中所有小于等于8的书中,离8最近的");
System.out.println(treeMap1.ceilingKey(8) + "在表中所有大于等于8的书中,离8最近的");
treeMap1.remove(5);
System.out.println(treeMap1.get(5) + ", 删掉就没有了");
题目一

在这里插入图片描述

//方法一
public static boolean isPalindrome1(Node head) {
    Stack<Node> stack = new Stack<>();
    Node cur = head;
    while (cur != null) {
        stack.push(cur);
        cur = cur.next;
    }
    while (head != null) {
        if (head.value != stack.pop().value) {
            return false;
        }

        head = head.next;
    }
    return true;
}

//方式二
//need n/2 extra space
//找快慢指针
public static boolean isPalindrome2(Node head) {
    if (head == null || head.next == null) {
        return true;
    }

    Node right = head.next;
    Node cur = head;
    while (cur.next != null && cur.next.next != null) {
        right = right.next;
        cur = cur.next.next;
    }
    Stack<Node> stack = new Stack<>();
    while (right != null) {  //压栈
        stack.push(right);
        right = right.next;
    }
    while (!stack.isEmpty()) {
        if (head.value != stack.pop().value) {  //不等于 返回false
            return false;
        }
        head = head.next;
    }
    return true;
}


//方式三
//need O(1) extra space
public static boolean isPalindrome3(Node head) {
    if (head == null || head.next == null) {
        return true;
    }
    Node n1 = head;
    Node n2 = head;
    while (n2.next != null && n2.next.next != null) {   //find mid node
        n1 = n1.next;
        n2 = n2.next.next;
    }

    n2 = n1.next;   //n1 ->mid
    n1.next = null; //mid.next -> null
    Node n3 = null;
    while (n2 != null) {  //right part convert
        n3 = n2.next;  //n3 -> save next node
        n2.next = n1;  //next of right node convert
        n1 = n2; //n1 move
        n2 = n3; //n2 move
    }
    n3 = n1; //n3->save last node
    n2 = head; //n2 -> left first node
    boolean res = true;
    while (n1 != null && n2 != null) {  //check paliindrome
        if (n1.value != n2.value) {
            res = false;
            break;
        }
        n1 = n1.next;  //left to mid
        n2 = n2.next;  //right to mid
    }
    n1 = n3.next;
    n3.next = null;
    while (n1 != null) {
        n2 = n1.next;
        n1.next = n2;
        n3 = n1;
        n1 = n2;
    }
    return res;

}

在这里插入图片描述

  public static Node listPartition2(Node head, int pivot) {
        Node sH = null; //samll head
        Node sT = null; //small tail
        Node eH = null; //equal head
        Node eT = null; //equal tail
        Node mH = null; //big head
        Node mT = null; //big tail
        Node next = null; //save next node
        //every node distributed to three lists
        while (head != null) {
            next = head.next;
            head.next = null;
            if (head.value < pivot) {
                if (sH == null) {
                    sH = head;
                    sT = head;
                } else {
                    sT.next = head;
                    sT = head;
                }
            } else if (head.value == pivot) {
                if (eH == null) {
                    eH = head;
                    eT = head;
                }else {
                    eT.next =head;
                    eT = head;
                }
            }else {
                if (mH == null){
                    mH =head;
                    mT = head;
                }else {
                    mT.next = head;
                    mT = head;
                }
            }
            head = next;
        }

        //small and equal reconnect
        if (sT != null){  //如果有小于区域
            sT.next = eH;
            eT = eT ==null?sT:eT;   //下一步,谁去连大于区域的头,谁就变成eT
        }
        //上面的if,不管跑了没有,et
        //all reconnect
        if (eT != null) { //如果小于区域和等于区域,不是都没有
               eT.next = mH;
        }
        return sH != null ? sH : (eH != null ? eH : mH);

    }
}
题目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eApDmgFf-1642420187367)(C:\Users\22445\AppData\Roaming\Typora\typora-user-images\image-20211117194726105.png)]

class Node{
    int value;
    Node next;
    Node rand;
    Node(int val){
        value = v
    }
}
 //hashmap实现问题
    public static Node copyListWithRand1(Node head) {
        HashMap<Node, Node> map = new HashMap<Node, Node>();
        Node cur = head;
        while (cur != null) { //将map对应关系记住
            map.put(cur, new Node(cur.value));
            cur = cur.next;
        }
        cur = head;
        while (cur != null) {
            //cur 老节点
            //map.get(cur) 这种方式可以找到新结点
            map.get(cur).next = map.get(cur.next);   //新结点的next = 当前旧节点的next对应的新结点
            map.get(cur).rand = map.get(cur.rand);
        }
        return map.get(head);
    }

    //不用哈希表的方式
    public static Node copyListWithRand2(Node head) {
        if (head == null) {  //如果链表为空则返回空
            return null;
        }
        Node cur = head;
        Node next = null;
        //copy node and link to every node
        //1 -> 2
        //1 -> 1` -> 2
        while (cur != null) {
            next = cur.next;   //旧节点给了next
            cur.next = new Node(cur.value);  //原next位置放入新节点
            cur.next.next = next;  //旧节点给next next
            cur = next;   //转移指针
        }
        cur = head;
        Node curCopy = null;
        //set copy node rand
        //1->1`->2->2`
        while (cur != null) {
            next = cur.next.next;
            curCopy = cur.next;
            curCopy.rand = (cur.rand != null) ? cur.rand.next : null;
            cur = next;
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值