星期二, 二月 23, 2016

326. Power of Three

Given an integer, write a function to determine if it is a power of three.

Follow up:

Could you do it without using any loop / recursion?

 

结题思路:

1、判断一个数是否是3的次方数,一个比较直接的方法是循环,判断n的因子是否全为3

class Solution {

public:

    bool isPowerOfThree(int n) {

        if(n==0)return false;

        while(n!=1){

            if(n%3)return false;

            n/=3;

        }

        return true;

    }

};

2、若不使用循环或递归,可以先求出tmp=log3(n),再求3^tmp,判断是否与n相等。Log3(n)=log(n)/log(3)=log10(n)/log10(3)。注意在使用logpow方法时,得到的数都是double,在转换为int时,可能要考虑到近似问题。建议首先将double转换为float,在将float转换为int

float a = 6.7f;

float b = a * 10;

int c = a * 10;

int d = b;

printf( "%d", c ); // 输出 66

printf( "%d", d ); // 输出 67

在解释结果前,得先了解几个知识点:

1. 即使在表达范围内,浮点数(floatdoublelong double)也不能精确表达每一个实数。

比如float可以精确表达67.0f,可以精确表达6.69999980926513671875f,但不能精确表达6.7f

当不能精确表达时,选择一个最接近的能精确表达的数,比如float6.69999980926513671875f来表达6.7f

2. 浮点数计算使用80387数字协处理器,把每一个浮点数载入80bits的临时实数中,进行计算,结果然后再放回。

3. 高精度浮点数转化为低精度浮点数时,使用低精度浮点数能表示的最接近的数;浮点数转化为整型时,直接取整数部分。

于是流程如下:

float a = 6.7f;   // a 6.69999980926513671875f

float b = a * 10; // 计算结果66.9999980926513671875l 放入 float 中时,变为67.0f,因为67.0ffloat能表示的,且最接近66.99……的数。

int c = a * 10;   // 计算结果66.9999980926513671875l 整数部分 66

int d = b;        // 67.0f 整数部分 67

可见,差别在于C是由long double直接取整数部分,而dlong double放到float后再取的整数部分,奥妙就在"long double放到float"这一阶段。

 

来自 <http://biancheng.dnbcw.info/c/434925.html>

 

 

class Solution {

public:

    bool isPowerOfThree(int n) {

        if(n==0)return false;

        double tmp=(log(n)/log(3));

        float tf=tmp*10;

        int ti=tf/10;

        if(pow(3,ti)==n)return true;

        return false;

    }

};

3、在discussion上看到使用fmod方法

头文件:math.h

用法:double fmod(double x,double y)

功能:计算xy的模

举例:

#include<stdio.h>

#include<math.h>

void main()

{

double a=2.8,b=0.2,c=0.0;

c=fmod(a,b); 

printf("a=%.16lf,b=%.16lf,c=%.16lf\n",a,b,c);

getch();

}

 

输出:

a=2.7999999999999998,b=0.2000000000000000,c=0.1999999999999997

class Solution {

public:

    bool isPowerOfThree(int n) {

        if(n==0)return false;

        return fmod(log10(n)/log10(3),1)==0;

    }

};

4、。。。。。。。。

星期一, 二月 22, 2016

List之Stack源码分析

源码版本为JDK1.7.0_75

该类继承自Vector,说明该类是可克隆的、可序列化的,且是同步的。

public

class Stack<E> extends Vector<E>

构造函数

public Stack() {

    }

 

入栈

    /**

* 将一个元素放入栈顶,通过vector类的addElement方法实现

     * Pushes an item onto the top of this stack. This has exactly

     * the same effect as:

     * <blockquote><pre>

     * addElement(item)</pre></blockquote>

     *

     * @param   item   the item to be pushed onto this stack.

     * @return  the <code>item</code> argument.

     * @see     java.util.Vector#addElement

     */

    public E push(E item) {

        addElement(item);

 

        return item;

    }

 

出栈

    /**

* 删除栈顶元素并将其返回,使用peek方法获取栈顶元素,使用vector类的removeElementAt方法完成元素的删除

     * Removes the object at the top of this stack and returns that

     * object as the value of this function.

     *

     * @return  The object at the top of this stack (the last item

     *          of the <tt>Vector</tt> object).

     * @throws  EmptyStackException  if this stack is empty.

     */

    public synchronized E pop() {

        E       obj;

        int     len = size();

 

        obj = peek();

        removeElementAt(len - 1);

 

        return obj;

    }

    /**

* 查看栈顶元素,但不将其从栈顶删除,使用vector类的elementAt方法实现。

     * Looks at the object at the top of this stack without removing it

     * from the stack.

     *

     * @return  the object at the top of this stack (the last item

     *          of the <tt>Vector</tt> object).

     * @throws  EmptyStackException  if this stack is empty.

     */

    public synchronized E peek() {

        int     len = size();

 

        if (len == 0)

            throw new EmptyStackException();

        return elementAt(len - 1);

    }

 

是否为空

    /**

     * Tests if this stack is empty.

     *

     * @return  <code>true</code> if and only if this stack contains

     *          no items; <code>false</code> otherwise.

     */

    public boolean empty() {

        return size() == 0;

    }

 

搜索

    /**

* vectorn-10对应栈顶到栈底,因此在搜索时,应使用lastIndexOf方法

     * Returns the 1-based position where an object is on this stack.

     * If the object <tt>o</tt> occurs as an item in this stack, this

     * method returns the distance from the top of the stack of the

     * occurrence nearest the top of the stack; the topmost item on the

     * stack is considered to be at distance <tt>1</tt>. The <tt>equals</tt>

     * method is used to compare <tt>o</tt> to the

     * items in this stack.

     *

     * @param   o   the desired object.

     * @return  the 1-based position from the top of the stack where

     *          the object is located; the return value <code>-1</code>

     *          indicates that the object is not on the stack.

     */

    public synchronized int search(Object o) {

        int i = lastIndexOf(o);

 

        if (i >= 0) {

            return size() - i;

        }

        return -1;

    }

 

 

318. Maximum Product of Word Lengths

Given a string array words, find the maximum value of length(word[i]) * length(word[j]) where the two words do not share common letters. You may assume that each word will contain only lower case letters. If no such two words exist, return 0.

Example 1:

Given ["abcw", "baz", "foo", "bar", "xtfn", "abcdef"]

Return 16

The two words can be "abcw", "xtfn".

Example 2:

Given ["a", "ab", "abc", "d", "cd", "bcd", "abcd"]

Return 4

The two words can be "ab", "cd".

Example 3:

Given ["a", "aa", "aaa", "aaaa"]

Return 0

No such pair of words.

解题思路:

该题目意思是给定一个string数组,找出最大的乘积(length(word[i])*length(word[j])),同时word[i]word[j]没有交集。

为了判断两个字符串是否有交集,首先将数组中的字符串用一个整数表示,整数中每一位对应一个小写字母。…..xxxxxxxxxxx对应……….fedcba。两个字符串是否有交集则将对应的整数进行与运算,若结果不为0,说明有交集。

由于在寻找最大乘积时,会频繁用到字符串的长度,因此可提前使用数组保存字符串长度(该过程在一定程度上会减少运行时间)

使用指针指向固定大小的数组相比于使用vector划分固定大小的数组,运行时间较少。

#include<vector>

#include<string>

#include<iostream>

#include<algorithm>

using namespace std;

class Solution {

public:

    int maxProduct(vector<string>& words) {

        int n=words.size();

        if(n<2)return 0;

        // 'vector<int>res' costs 20ms more than using 'int*res=new int[n]'

        //vector<int>res=vector<int>(n,0);

        int*res=new int[n];

        // using array len to store the length of words,it can improve the time.

        int*len=new int[n];

        for(int i=0;i<n;i++){

            //string word=words[i];

            //transform(word.begin(),word.end(),word.begin(),::tolower);

            res[i]=0;

            len[i]=words[i].size();

            int l=words[i].size();

            for(int j=0;j<l;j++){

                res[i]|=1<<(words[i][j]-'a');

            }

            //res[i]=bit;

            //cout<<bit<<endl;

        }

        int max=0;

        for(int i=0;i<n;i++){

            for(int j=i+1;j<n;j++)

                if(!(res[i]&res[j])){

                    int tmp=len[i]*len[j];

                    if(max<tmp)max=tmp;

                }

        }

        return max;

    }

};

//int main(){

//  vector<string>v;

//  int n;

//  cin>>n;

//  for(int i=0;i<n;i++){

//      string tmp;

//      cin>>tmp;

//      v.push_back(tmp);

//  }

//  Solution test=Solution();

//  cout<<test.maxProduct(v)<<endl;

//  system("pause");

//  return 0;

//}

 

 

星期六, 二月 20, 2016

List之Vector源码分析

源码版本为JDK1.7.0_75
public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
Vector继承了AbstractList,实现了List接口,可以被当作list使用;实现了RandomAccess接口,该接口是一个标记接口,表明该类支持快速随机访问;实现了Cloneable接口,说明该类可以被克隆;实现了Serializable接口,说明该类可以支持序列化(看到网上有说vector类没有实现Serializable接口,可是明明已经实现了【implements java.io.Serializable】??)Vector中的大部分方法使用了synchronized,故Vector是同步的。

使用了synchronized修饰的方法包括copyIntotrimToSizeensureCapacitysetSizecapacitysizeisEmptyindexOflastIndexOfelementAtfirstElementlastElementsetElementAtremoveElementAtinsertElementAtaddElementremoveElementremoveAllElementsclonetoArraygetsetaddremovecontainsAlladdAllremoveAllretainAlladdAllequalshashCodetoStringsubListremoveRangewriteObjectlistIteratoriterator等。

成员变量
可以看出Vector类使用数组实现。
    /**
* 该数组保存vecor内容。vector的容量是该数组的长度,该数组足够大包含vector所有元素。
     * The array buffer into which the components of the vector are
     * stored. The capacity of the vector is the length of this array buffer,
     * and is at least large enough to contain all the vector's elements.
     *
     * <p>Any array elements following the last element in the Vector are null.
     *
     * @serial
     */
    protected Object[] elementData;

    /**
* vector对象的元素数目,有可能出现elementData开辟了空间,但vector没有元素的情况。
     * The number of valid components in this {@code Vector} object.
     * Components {@code elementData[0]} through
     * {@code elementData[elementCount-1]} are the actual items.
     *
     * @serial
     */
    protected int elementCount;

    /**
* elementData大小大于vector容量时,容量自动增长倍数。若容量增长小于等于0,则vector容量在每次需要扩充时,加倍增长。
     * The amount by which the capacity of the vector is automatically
     * incremented when its size becomes greater than its capacity.  If
     * the capacity increment is less than or equal to zero, the capacity
     * of the vector is doubled each time it needs to grow.
     *
     * @serial
     */
    protected int capacityIncrement;

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -2767605614048989439L;

构造函数
    /**
* 构造一个指定了初始容量和容量增量的空vector
     * Constructs an empty vector with the specified initial capacity and
     * capacity increment.
     *
     * @param   initialCapacity     the initial capacity of the vector
     * @param   capacityIncrement   the amount by which the capacity is
     *                              increased when the vector overflows
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }

    /**
* 构造一个指定了初始容量的空vecor
     * Constructs an empty vector with the specified initial capacity and
     * with its capacity increment equal to zero.
     *
     * @param   initialCapacity   the initial capacity of the vector
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    public Vector(int initialCapacity) {
        this(initialCapacity, 0);
    }

    /**
* 构造一个空vector,默认情况下初始容量大小为10,增量为0.
     * Constructs an empty vector so that its internal data array
     * has size {@code 10} and its standard capacity increment is
     * zero.
     */
    public Vector() {
        this(10);
    }

    /**
* 构造一个包含特定集合元素的vector
     * Constructs a vector containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param c the collection whose elements are to be placed into this
     *       vector
     * @throws NullPointerException if the specified collection is null
     * @since   1.2
     */
    public Vector(Collection<? extends E> c) {
        elementData = c.toArray();
        elementCount = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
    }

方法

扩充容量
    /**
     * Increases the capacity of this vector, if necessary, to ensure
     * that it can hold at least the number of components specified by
     * the minimum capacity argument.
     *
     * <p>If the current capacity of this vector is less than
     * {@code minCapacity}, then its capacity is increased by replacing its
     * internal data array, kept in the field {@code elementData}, with a
     * larger one.  The size of the new data array will be the old size plus
     * {@code capacityIncrement}, unless the value of
     * {@code capacityIncrement} is less than or equal to zero, in which case
     * the new capacity will be twice the old capacity; but if this new size
     * is still smaller than {@code minCapacity}, then the new capacity will
     * be {@code minCapacity}.
     *
     * @param minCapacity the desired minimum capacity
     */
    public synchronized void ensureCapacity(int minCapacity) {
        if (minCapacity > 0) {
            modCount++;
            ensureCapacityHelper(minCapacity);
        }
    }

    /**
     * This implements the unsynchronized semantics of ensureCapacity.
     * Synchronized methods in this class can internally call this
     * method for ensuring capacity without incurring the cost of an
     * extra synchronization.
     *
     * @see #ensureCapacity(int)
     */
    private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    /**
     * The maximum size of array to allocate.
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
     * capacityIncrement大于0,则至少增加capacityIncrement大小;否则至少增加
     * elementData.length大小。
     */
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

容量和长度大小
elementData.lengthelementData数组的长度,而elementCountvector实际元素个数,两者不一定相等。方法capacity指所给的空间,因此返回的是elementData数组的长度,而方法size则返回的是vector元素个数,即elementCount。方法isEmpty判断的是vector中是否有元素,而不是判断是否有空间,因此使用的是变量elementCount
    /**
* 返回vector当前容量
     * Returns the current capacity of this vector.
     *
     * @return  the current capacity (the length of its internal
     *          data array, kept in the field {@code elementData}
     *          of this vector)
     */
    public synchronized int capacity() {
        return elementData.length;
    }

    /**
* 返回vector元素个数
     * Returns the number of components in this vector.
     *
     * @return  the number of components in this vector
     */
    public synchronized int size() {
        return elementCount;
    }

    /**
* 测试vector是否没有包含元素
     * Tests if this vector has no components.
     *
     * @return  {@code true} if and only if this vector has
     *          no components, that is, its size is zero;
     *          {@code false} otherwise.
     */
    public synchronized boolean isEmpty() {
        return elementCount == 0;
    }

枚举
该方法返回一个实现了接口Enumeration的匿名内部类,Enumeration接口需要实现hasMoreElementsnextElement两个方法。其中nextElement方法中的synchronized (Vector.this) {}表示同步块,表示当两个并发线程访问同一个vector对象的同步代码块时,一个时间内只能有一个线程得到执行,另一个线程要等待当前线程执行完这个代码块以后才能执行该代码块。
    /**
* 返回对该vector元素进行枚举的Enumeration类。
     * Returns an enumeration of the components of this vector. The
     * returned {@code Enumeration} object will generate all items in
     * this vector. The first item generated is the item at index {@code 0},
     * then the item at index {@code 1}, and so on.
     *
     * @return  an enumeration of the components of this vector
     * @see     Iterator
     */
    public Enumeration<E> elements() {
        return new Enumeration<E>() {
            int count = 0;

            public boolean hasMoreElements() {
                return count < elementCount;
            }

            public E nextElement() {
                synchronized (Vector.this) {
                    if (count < elementCount) {
                        return elementData(count++);
                    }
                }
                throw new NoSuchElementException("Vector Enumeration");
            }
        };
    }

添加元素时,首先都需要对容量进行扩充
    /**
     * Inserts the specified object as a component in this vector at the
     * specified {@code index}. Each component in this vector with
     * an index greater or equal to the specified {@code index} is
     * shifted upward to have an index one greater than the value it had
     * previously.
     *
     * <p>The index must be a value greater than or equal to {@code 0}
     * and less than or equal to the current size of the vector. (If the
     * index is equal to the current size of the vector, the new element
     * is appended to the Vector.)
     *
     * <p>This method is identical in functionality to the
     * {@link #add(int, Object) add(int, E)}
     * method (which is part of the {@link List} interface).  Note that the
     * {@code add} method reverses the order of the parameters, to more closely
     * match array usage.
     *
     * @param      obj     the component to insert
     * @param      index   where to insert the new component
     * @throws ArrayIndexOutOfBoundsException if the index is out of range
     *         ({@code index < 0 || index > size()})
     */
    public synchronized void insertElementAt(E obj, int index) {
        modCount++;
        if (index > elementCount) {
            throw new ArrayIndexOutOfBoundsException(index
                                                     + " > " + elementCount);
        }
        ensureCapacityHelper(elementCount + 1);
        System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
        elementData[index] = obj;
        elementCount++;
    }

    /**
     * Adds the specified component to the end of this vector,
     * increasing its size by one. The capacity of this vector is
     * increased if its size becomes greater than its capacity.
     *
     * <p>This method is identical in functionality to the
     * {@link #add(Object) add(E)}
     * method (which is part of the {@link List} interface).
     *
     * @param   obj   the component to be added
     */
    public synchronized void addElement(E obj) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = obj;
    }
    /**
     * Appends the specified element to the end of this Vector.
     *
     * @param e element to be appended to this Vector
     * @return {@code true} (as specified by {@link Collection#add})
     * @since 1.2
     */
    public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }
    /**
     * Inserts the specified element at the specified position in this Vector.
     * Shifts the element currently at that position (if any) and any
     * subsequent elements to the right (adds one to their indices).
     *
     * @param index index at which the specified element is to be inserted
     * @param element element to be inserted
     * @throws ArrayIndexOutOfBoundsException if the index is out of range
     *         ({@code index < 0 || index > size()})
     * @since 1.2
     */
    public void add(int index, E element) {
        insertElementAt(element, index);
    }

克隆
方法clone并没有将elementCountcapacityIncrement的值也复制到新的vector中。
    /**
     * Returns a clone of this vector. The copy will contain a
     * reference to a clone of the internal data array, not a reference
     * to the original internal data array of this {@code Vector} object.
     *
     * @return  a clone of this vector
     */
    public synchronized Object clone() {
        try {
            @SuppressWarnings("unchecked")
                Vector<E> v = (Vector<E>) super.clone();
            v.elementData = Arrays.copyOf(elementData, elementCount);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError();
        }
    }

大容量操作(Bulk Operations
containsAlladdAllremoveAllretainAll

    /**
     * Returns the hash code value for this Vector.
     */
    public synchronized int hashCode() {
        return super.hashCode();
    }

该方法通过集合Collections.synchronizedList将返回的list转换为一个线程安全的类。
    /**
     * Returns a view of the portion of this List between fromIndex,
     * inclusive, and toIndex, exclusive.  (If fromIndex and toIndex are
     * equal, the returned List is empty.)  The returned List is backed by this
     * List, so changes in the returned List are reflected in this List, and
     * vice-versa.  The returned List supports all of the optional List
     * operations supported by this List.
     *
     * <p>This method eliminates the need for explicit range operations (of
     * the sort that commonly exist for arrays).  Any operation that expects
     * a List can be used as a range operation by operating on a subList view
     * instead of a whole List.  For example, the following idiom
     * removes a range of elements from a List:
     * <pre>
     *      list.subList(from, to).clear();
     * </pre>
     * Similar idioms may be constructed for indexOf and lastIndexOf,
     * and all of the algorithms in the Collections class can be applied to
     * a subList.
     *
     * <p>The semantics of the List returned by this method become undefined if
     * the backing list (i.e., this List) is <i>structurally modified</i> in
     * any way other than via the returned List.  (Structural modifications are
     * those that change the size of the List, or otherwise perturb it in such
     * a fashion that iterations in progress may yield incorrect results.)
     *
     * @param fromIndex low endpoint (inclusive) of the subList
     * @param toIndex high endpoint (exclusive) of the subList
     * @return a view of the specified range within this List
     * @throws IndexOutOfBoundsException if an endpoint index value is out of range
     *         {@code (fromIndex < 0 || toIndex > size)}
     * @throws IllegalArgumentException if the endpoint indices are out of order
     *         {@code (fromIndex > toIndex)}
     */
    public synchronized List<E> subList(int fromIndex, int toIndex) {
        return Collections.synchronizedList(super.subList(fromIndex, toIndex),
                                            this);
    }

总结:
1Vector有四个不同的构造方法。无参构造方法的容量默认为10,增量为0.
2、扩充容量的方法ensureCapacity,与ArrayList类似,但Vector可以自定义至少扩充的增量(capacityIncrement)。
3Vector是同步的,而ArrayListLinkedList是非同步的。为了保证一些方法的同步,使用了synchronized修饰;保证一些代码的执行的同步,使用了同步块;保证list的同步,使用了Collection.synchronizedList方法。
4、与ArrayListLinkedList类似,Vector允许元素为null
5Vector的容量(capacity)和大小(size)是有区别的。